Kaynağa Gözat

LibGL: Add back face culling functions

Adds all needed functions to support back face culling
and implements back face culling in the SoftwareGLContext.
Stephan Unverwerth 4 yıl önce
ebeveyn
işleme
e6c0600499

+ 16 - 0
Userland/Libraries/LibGL/GL/gl.h

@@ -32,11 +32,19 @@ extern "C" {
 // Buffer bits
 #define GL_COLOR_BUFFER_BIT 0x0200
 
+// Enable capabilities
+#define GL_CULL_FACE 0x0B44
+
 // Utility
 #define GL_VENDOR 0x1F00
 #define GL_RENDERER 0x1F01
 #define GL_VERSION 0x1F02
 
+// Culled face side
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_FRONT_AND_BACK 0x0408
+
 // Error codes
 #define GL_NO_ERROR 0
 #define GL_INVALID_ENUM 0x500
@@ -47,6 +55,10 @@ extern "C" {
 #define GL_OUT_OF_MEMORY 0x505
 #define GL_INVALID_FRAMEBUFFER_OPERATION 0x506
 
+// Triangle winding order
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+
 //
 // OpenGL typedefs
 //
@@ -96,6 +108,10 @@ GLAPI void glVertex2fv(const GLfloat* v);
 GLAPI void glVertex3f(GLfloat x, GLfloat y, GLfloat z);
 GLAPI void glVertex3fv(const GLfloat* v);
 GLAPI void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void glEnable(GLenum cap);
+GLAPI void glDisable(GLenum cap);
+GLAPI void glCullFace(GLenum mode);
+GLAPI void glFrontFace(GLenum mode);
 
 #ifdef __cplusplus
 }

+ 4 - 0
Userland/Libraries/LibGL/GLContext.h

@@ -36,6 +36,10 @@ public:
     virtual void gl_translate(GLdouble x, GLdouble y, GLdouble z) = 0;
     virtual void gl_vertex(GLdouble x, GLdouble y, GLdouble z, GLdouble w) = 0;
     virtual void gl_viewport(GLint x, GLint y, GLsizei width, GLsizei height) = 0;
+    virtual void gl_enable(GLenum) = 0;
+    virtual void gl_disable(GLenum) = 0;
+    virtual void gl_front_face(GLenum) = 0;
+    virtual void gl_cull_face(GLenum) = 0;
 };
 
 OwnPtr<GLContext> create_context();

+ 20 - 0
Userland/Libraries/LibGL/GLUtils.cpp

@@ -10,6 +10,26 @@
 
 extern GL::GLContext* g_gl_context;
 
+void glEnable(GLenum cap)
+{
+    g_gl_context->gl_enable(cap);
+}
+
+void glDisable(GLenum cap)
+{
+    g_gl_context->gl_disable(cap);
+}
+
+void glFrontFace(GLenum mode)
+{
+    g_gl_context->gl_front_face(mode);    
+}
+
+void glCullFace(GLenum mode)
+{
+    g_gl_context->gl_cull_face(mode);    
+}
+
 void glClear(GLbitfield mask)
 {
     g_gl_context->gl_clear(mask);

+ 64 - 0
Userland/Libraries/LibGL/SoftwareGLContext.cpp

@@ -404,6 +404,16 @@ void SoftwareGLContext::gl_end()
         (void)(vertexBy);
         (void)(vertexCx);
         (void)(vertexCy);
+        
+        if (m_cull_faces) {
+            bool is_front = (m_front_face == GL_CCW ? area > 0 : area < 0);
+
+            if (is_front && (m_culled_sides == GL_FRONT || m_culled_sides == GL_FRONT_AND_BACK))
+                continue;
+
+            if (!is_front && (m_culled_sides == GL_BACK || m_culled_sides == GL_FRONT_AND_BACK))
+                continue;
+        }
     }
 
     triangle_list.clear();
@@ -714,4 +724,58 @@ void SoftwareGLContext::gl_viewport(GLint x, GLint y, GLsizei width, GLsizei hei
     m_error = GL_NO_ERROR;
 }
 
+void SoftwareGLContext::gl_enable(GLenum capability)
+{
+    if (m_in_draw_state) {
+        m_error = GL_INVALID_OPERATION;
+        return;
+    }
+
+    switch (capability) {
+    case GL_CULL_FACE:
+        m_cull_faces = true;
+        break;
+    default:
+        m_error = GL_INVALID_ENUM;
+        break;
+    }
+}
+
+void SoftwareGLContext::gl_disable(GLenum capability)
+{
+    if (m_in_draw_state) {
+        m_error = GL_INVALID_OPERATION;
+        return;
+    }
+
+    switch (capability) {
+    case GL_CULL_FACE:
+        m_cull_faces = false;
+        break;
+    default:
+        m_error = GL_INVALID_ENUM;
+        break;
+    }
+}
+
+void SoftwareGLContext::gl_front_face(GLenum face)
+{
+    if (face < GL_CW || face > GL_CCW) {
+        m_error = GL_INVALID_ENUM;
+        return;
+    }
+
+    m_front_face = face;
+}
+
+void SoftwareGLContext::gl_cull_face(GLenum cull_mode)
+{
+    if (cull_mode < GL_FRONT || cull_mode > GL_FRONT_AND_BACK) {
+        m_error = GL_INVALID_ENUM;
+        return;
+    }
+
+    m_culled_sides = cull_mode;
+}
+
 }

+ 8 - 0
Userland/Libraries/LibGL/SoftwareGLContext.h

@@ -35,6 +35,10 @@ public:
     virtual void gl_translate(GLdouble x, GLdouble y, GLdouble z) override;
     virtual void gl_vertex(GLdouble x, GLdouble y, GLdouble z, GLdouble w) override;
     virtual void gl_viewport(GLint x, GLint y, GLsizei width, GLsizei height) override;
+    virtual void gl_enable(GLenum) override;
+    virtual void gl_disable(GLenum) override;
+    virtual void gl_front_face(GLenum) override;
+    virtual void gl_cull_face(GLenum) override;
 
 private:
     GLenum m_current_draw_mode;
@@ -56,6 +60,10 @@ private:
 
     GLenum m_error = GL_NO_ERROR;
     bool m_in_draw_state = false;
+
+    bool m_cull_faces = false;
+    GLenum m_front_face = GL_CCW;
+    GLenum m_culled_sides = GL_BACK;
 };
 
 }