void OpenGLState::Apply() const { // Culling if (cull.enabled != cur_state.cull.enabled) { if (cull.enabled) { glEnable(GL_CULL_FACE); } else { glDisable(GL_CULL_FACE); } } if (cull.mode != cur_state.cull.mode) { glCullFace(cull.mode); } if (cull.front_face != cur_state.cull.front_face) { glFrontFace(cull.front_face); } // Depth test if (depth.test_enabled != cur_state.depth.test_enabled) { if (depth.test_enabled) { glEnable(GL_DEPTH_TEST); } else { glDisable(GL_DEPTH_TEST); } } if (depth.test_func != cur_state.depth.test_func) { glDepthFunc(depth.test_func); } // Depth mask if (depth.write_mask != cur_state.depth.write_mask) { glDepthMask(depth.write_mask); } // Color mask if (color_mask.red_enabled != cur_state.color_mask.red_enabled || color_mask.green_enabled != cur_state.color_mask.green_enabled || color_mask.blue_enabled != cur_state.color_mask.blue_enabled || color_mask.alpha_enabled != cur_state.color_mask.alpha_enabled) { glColorMask(color_mask.red_enabled, color_mask.green_enabled, color_mask.blue_enabled, color_mask.alpha_enabled); } // Stencil test if (stencil.test_enabled != cur_state.stencil.test_enabled) { if (stencil.test_enabled) { glEnable(GL_STENCIL_TEST); } else { glDisable(GL_STENCIL_TEST); } } if (stencil.test_func != cur_state.stencil.test_func || stencil.test_ref != cur_state.stencil.test_ref || stencil.test_mask != cur_state.stencil.test_mask) { glStencilFunc(stencil.test_func, stencil.test_ref, stencil.test_mask); } if (stencil.action_depth_fail != cur_state.stencil.action_depth_fail || stencil.action_depth_pass != cur_state.stencil.action_depth_pass || stencil.action_stencil_fail != cur_state.stencil.action_stencil_fail) { glStencilOp(stencil.action_stencil_fail, stencil.action_depth_fail, stencil.action_depth_pass); } // Stencil mask if (stencil.write_mask != cur_state.stencil.write_mask) { glStencilMask(stencil.write_mask); } // Blending if (blend.enabled != cur_state.blend.enabled) { if (blend.enabled) { glEnable(GL_BLEND); glDisable(GL_COLOR_LOGIC_OP); } else { glDisable(GL_BLEND); glEnable(GL_COLOR_LOGIC_OP); } } if (blend.color.red != cur_state.blend.color.red || blend.color.green != cur_state.blend.color.green || blend.color.blue != cur_state.blend.color.blue || blend.color.alpha != cur_state.blend.color.alpha) { glBlendColor(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha); } if (blend.src_rgb_func != cur_state.blend.src_rgb_func || blend.dst_rgb_func != cur_state.blend.dst_rgb_func || blend.src_a_func != cur_state.blend.src_a_func || blend.dst_a_func != cur_state.blend.dst_a_func) { glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func, blend.dst_a_func); } if (blend.rgb_equation != cur_state.blend.rgb_equation || blend.a_equation != cur_state.blend.a_equation) { glBlendEquationSeparate(blend.rgb_equation, blend.a_equation); } if (logic_op != cur_state.logic_op) { glLogicOp(logic_op); } // Textures for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) { if (texture_units[i].texture_2d != cur_state.texture_units[i].texture_2d) { glActiveTexture(TextureUnits::PicaTexture(i).Enum()); glBindTexture(GL_TEXTURE_2D, texture_units[i].texture_2d); } if (texture_units[i].sampler != cur_state.texture_units[i].sampler) { glBindSampler(i, texture_units[i].sampler); } } if (texture_cube_unit.texture_cube != cur_state.texture_cube_unit.texture_cube) { glActiveTexture(TextureUnits::TextureCube.Enum()); glBindTexture(GL_TEXTURE_CUBE_MAP, texture_cube_unit.texture_cube); } if (texture_cube_unit.sampler != cur_state.texture_cube_unit.sampler) { glBindSampler(TextureUnits::TextureCube.id, texture_cube_unit.sampler); } // Texture buffer LUTs if (texture_buffer_lut_rg.texture_buffer != cur_state.texture_buffer_lut_rg.texture_buffer) { glActiveTexture(TextureUnits::TextureBufferLUT_RG.Enum()); glBindTexture(GL_TEXTURE_BUFFER, texture_buffer_lut_rg.texture_buffer); } // Texture buffer LUTs if (texture_buffer_lut_rgba.texture_buffer != cur_state.texture_buffer_lut_rgba.texture_buffer) { glActiveTexture(TextureUnits::TextureBufferLUT_RGBA.Enum()); glBindTexture(GL_TEXTURE_BUFFER, texture_buffer_lut_rgba.texture_buffer); } // Shadow Images if (image_shadow_buffer != cur_state.image_shadow_buffer) { glBindImageTexture(ImageUnits::ShadowBuffer, image_shadow_buffer, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); } if (image_shadow_texture_px != cur_state.image_shadow_texture_px) { glBindImageTexture(ImageUnits::ShadowTexturePX, image_shadow_texture_px, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI); } if (image_shadow_texture_nx != cur_state.image_shadow_texture_nx) { glBindImageTexture(ImageUnits::ShadowTextureNX, image_shadow_texture_nx, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI); } if (image_shadow_texture_py != cur_state.image_shadow_texture_py) { glBindImageTexture(ImageUnits::ShadowTexturePY, image_shadow_texture_py, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI); } if (image_shadow_texture_ny != cur_state.image_shadow_texture_ny) { glBindImageTexture(ImageUnits::ShadowTextureNY, image_shadow_texture_ny, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI); } if (image_shadow_texture_pz != cur_state.image_shadow_texture_pz) { glBindImageTexture(ImageUnits::ShadowTexturePZ, image_shadow_texture_pz, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI); } if (image_shadow_texture_nz != cur_state.image_shadow_texture_nz) { glBindImageTexture(ImageUnits::ShadowTextureNZ, image_shadow_texture_nz, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI); } // Framebuffer if (draw.read_framebuffer != cur_state.draw.read_framebuffer) { glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer); } if (draw.draw_framebuffer != cur_state.draw.draw_framebuffer) { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw.draw_framebuffer); } // Vertex array if (draw.vertex_array != cur_state.draw.vertex_array) { glBindVertexArray(draw.vertex_array); } // Vertex buffer if (draw.vertex_buffer != cur_state.draw.vertex_buffer) { glBindBuffer(GL_ARRAY_BUFFER, draw.vertex_buffer); } // Uniform buffer if (draw.uniform_buffer != cur_state.draw.uniform_buffer) { glBindBuffer(GL_UNIFORM_BUFFER, draw.uniform_buffer); } // Shader program if (draw.shader_program != cur_state.draw.shader_program) { glUseProgram(draw.shader_program); } // Program pipeline if (draw.program_pipeline != cur_state.draw.program_pipeline) { glBindProgramPipeline(draw.program_pipeline); } // Scissor test if (scissor.enabled != cur_state.scissor.enabled) { if (scissor.enabled) { glEnable(GL_SCISSOR_TEST); } else { glDisable(GL_SCISSOR_TEST); } } if (scissor.x != cur_state.scissor.x || scissor.y != cur_state.scissor.y || scissor.width != cur_state.scissor.width || scissor.height != cur_state.scissor.height) { glScissor(scissor.x, scissor.y, scissor.width, scissor.height); } if (viewport.x != cur_state.viewport.x || viewport.y != cur_state.viewport.y || viewport.width != cur_state.viewport.width || viewport.height != cur_state.viewport.height) { glViewport(viewport.x, viewport.y, viewport.width, viewport.height); } // Clip distance for (size_t i = 0; i < clip_distance.size(); ++i) { if (clip_distance[i] != cur_state.clip_distance[i]) { if (clip_distance[i]) { glEnable(GL_CLIP_DISTANCE0 + static_cast<GLenum>(i)); } else { glDisable(GL_CLIP_DISTANCE0 + static_cast<GLenum>(i)); } } } cur_state = *this; }
/* * OpenGL (GLUT) calls this routine to display the scene */ void display() { int i,j; const double len=2.0; // Length of axes // Light position and colors float Ambient[] = {0.3,0.3,0.3,1.0}; float Diffuse[] = {1.0,1.0,1.0,1.0}; float Position[] = {Cos(zh),Ylight,Sin(zh),1.0}; // Erase the window and the depth buffer glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); // Enable Z-buffering in OpenGL glEnable(GL_DEPTH_TEST); // Undo previous transformations glLoadIdentity(); // Perspective - set eye position if (proj) { double Ex = -2*dim*Sin(th)*Cos(ph); double Ey = +2*dim *Sin(ph); double Ez = +2*dim*Cos(th)*Cos(ph); gluLookAt(Ex,Ey,Ez , 0,0,0 , 0,Cos(ph),0); } // Orthogonal - set world orientation else { glRotatef(ph,1,0,0); glRotatef(th,0,1,0); } // Draw light position as sphere (still no lighting here) glColor3f(1,1,1); glPushMatrix(); glTranslated(Position[0],Position[1],Position[2]); glutSolidSphere(0.03,10,10); glPopMatrix(); // OpenGL should normalize normal vectors glEnable(GL_NORMALIZE); // Enable lighting glEnable(GL_LIGHTING); // glColor sets ambient and diffuse color materials glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL); // Enable light 0 glEnable(GL_LIGHT0); // Set ambient, diffuse, specular components and position of light 0 glLightfv(GL_LIGHT0,GL_AMBIENT ,Ambient); glLightfv(GL_LIGHT0,GL_DIFFUSE ,Diffuse); glLightfv(GL_LIGHT0,GL_POSITION,Position); // Draw floor glEnable(GL_TEXTURE_2D); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1,1); glColor3f(1,1,1); glNormal3f(0,1,0); for (j=-Dfloor;j<Dfloor;j++) { glBegin(GL_QUAD_STRIP); for (i=-Dfloor;i<=Dfloor;i++) { glTexCoord2f(i,j); glVertex3f(i,Yfloor,j); glTexCoord2f(i,j+1); glVertex3f(i,Yfloor,j+1); } glEnd(); } glDisable(GL_POLYGON_OFFSET_FILL); glDisable(GL_TEXTURE_2D); // Draw scene glColor3f(1,1,0); scene(); // Save what is glEnabled glPushAttrib(GL_ENABLE_BIT); // Draw shadow switch (mode) { // No shadow case 0: break; // Draw flattened scene case 1: glPushMatrix(); ShadowProjection(Position,E,N); scene(); glPopMatrix(); break; // Transformation with lighting disabled case 2: glDisable(GL_LIGHTING); // Draw flattened scene glPushMatrix(); ShadowProjection(Position,E,N); scene(); glPopMatrix(); break; // Set shadow color case 3: glDisable(GL_LIGHTING); glColor3f(0.3,0.3,0.3); // Draw flattened scene glPushMatrix(); ShadowProjection(Position,E,N); scene(); glPopMatrix(); break; // Blended shadows case 4: glDisable(GL_LIGHTING); // Blended color glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glColor4f(0,0,0,0.4); // Draw flattened scene glPushMatrix(); ShadowProjection(Position,E,N); scene(); glPopMatrix(); break; // Blended shadows Z-buffer masked case 5: glDisable(GL_LIGHTING); // Draw blended glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glColor4f(0,0,0,0.4); // Make Z-buffer read-only glDepthMask(0); // Draw flattened scene glPushMatrix(); ShadowProjection(Position,E,N); scene(); glPopMatrix(); // Make Z-buffer read-write glDepthMask(1); break; // Blended with stencil buffer case 6: glDisable(GL_LIGHTING); // Enable stencil operations glEnable(GL_STENCIL_TEST); /* * Step 1: Set stencil buffer to 1 where there are shadows */ // Existing value of stencil buffer doesn't matter glStencilFunc(GL_ALWAYS,1,0xFFFFFFFF); // Set the value to 1 (REF=1 in StencilFunc) // only if Z-buffer would allow write glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE); // Make Z-buffer and color buffer read-only glDepthMask(0); glColorMask(0,0,0,0); // Draw flattened scene glPushMatrix(); ShadowProjection(Position,E,N); scene(); glPopMatrix(); // Make Z-buffer and color buffer read-write glDepthMask(1); glColorMask(1,1,1,1); /* * Step 2: Draw shadow masked by stencil buffer */ // Set the stencil test draw where stencil buffer is > 0 glStencilFunc(GL_LESS,0,0xFFFFFFFF); // Make the stencil buffer read-only glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP); // Enable blending glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glColor4f(0,0,0,0.5); // Draw the shadow over the entire floor glBegin(GL_QUADS); glVertex3f(-Dfloor,Yfloor,-Dfloor); glVertex3f(+Dfloor,Yfloor,-Dfloor); glVertex3f(+Dfloor,Yfloor,+Dfloor); glVertex3f(-Dfloor,Yfloor,+Dfloor); glEnd(); break; default: break; } // Undo glEnables glPopAttrib(); // Draw axes - no lighting from here on glDisable(GL_LIGHTING); glColor3f(1,1,1); if (axes) { glBegin(GL_LINES); glVertex3d(0.0,0.0,0.0); glVertex3d(len,0.0,0.0); glVertex3d(0.0,0.0,0.0); glVertex3d(0.0,len,0.0); glVertex3d(0.0,0.0,0.0); glVertex3d(0.0,0.0,len); glEnd(); // Label axes glRasterPos3d(len,0.0,0.0); Print("X"); glRasterPos3d(0.0,len,0.0); Print("Y"); glRasterPos3d(0.0,0.0,len); Print("Z"); } // Display parameters glWindowPos2i(5,5); Print("Angle=%d,%d Dim=%.1f Projection=%s Light Elevation=%.1f", th,ph,dim,proj?"Perpective":"Orthogonal",Ylight); glWindowPos2i(5,25); Print(text[mode]); // Render the scene and make it visible ErrCheck("display"); glFlush(); glutSwapBuffers(); }
static void DrawStencilPixels(GLint x, GLint y, GLsizei w, GLsizei h, const GLubyte *stencil) { /* This program is run eight times, once for each stencil bit. * The stencil values to draw are found in an 8-bit alpha texture. * We read the texture/stencil value and test if bit 'b' is set. * If the bit is set, result.A will be non-zero. Finally, use * alpha test and stencil test to update the stencil buffer. * * The basic algorithm for checking if a bit is set is: * if (is_odd(value / (1 << bit))) * result is one (or non-zero). * else * result is zero. * The program parameter contains two values: * parm.x = 255 / (1 << bit) * parm.y = 0.5 */ static const char *program = "!!ARBfp1.0\n" "PARAM parm = program.local[0]; \n" "TEMP t; \n" "TEX t, fragment.texcoord[0], texture[0], RECT; \n" "# t = t * 255 / bit \n" "MUL t.x, t.a, parm.x; \n" "# t = (int) t \n" "FRC t.y, t.x; \n" "SUB t.x, t.x, t.y; \n" "# t = 5 * 0.5 \n" "MUL t.x, t.x, parm.y; \n" "# alpha = frac(t) \n" "FRC result.color, t.x; \n" "END \n"; GLuint prog; GLint bit; glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, stencil); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glGenProgramsARB(1, &prog); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(program), (const GLubyte *) program); glEnable(GL_FRAGMENT_PROGRAM_ARB); glPushMatrix(); glTranslatef(x, y, 0); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0); glEnable(GL_STENCIL_TEST); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); for (bit = 0; bit < 8; bit++) { GLuint mask = 1 << bit; glStencilFunc(GL_ALWAYS, 255/*mask*/, mask); glStencilMask(mask); glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, // 1.0 / bit, 0.5, 0.0, 0.0); 255.0 / mask, 0.5, 0.0, 0.0); glBegin(GL_TRIANGLE_FAN); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(w, 0); glVertex2f(w, 0); glTexCoord2f(w, h); glVertex2f(w, h); glTexCoord2f(0, h); glVertex2f(0, h); glEnd(); } glPopMatrix(); glDisable(GL_FRAGMENT_PROGRAM_ARB); glDisable(GL_ALPHA_TEST); glDisable(GL_STENCIL_TEST); }
/// // Initialize the stencil buffer values, and then use those // values to control rendering // void Draw ( ESContext *esContext ) { int i; UserData *userData = esContext->userData; GLfloat vVertices[] = { -0.75f, 0.25f, 0.50f, // Quad #0 -0.25f, 0.25f, 0.50f, -0.25f, 0.75f, 0.50f, -0.75f, 0.75f, 0.50f, 0.25f, 0.25f, 0.90f, // Quad #1 0.75f, 0.25f, 0.90f, 0.75f, 0.75f, 0.90f, 0.25f, 0.75f, 0.90f, -0.75f, -0.75f, 0.50f, // Quad #2 -0.25f, -0.75f, 0.50f, -0.25f, -0.25f, 0.50f, -0.75f, -0.25f, 0.50f, 0.25f, -0.75f, 0.50f, // Quad #3 0.75f, -0.75f, 0.50f, 0.75f, -0.25f, 0.50f, 0.25f, -0.25f, 0.50f, -1.00f, -1.00f, 0.00f, // Big Quad 1.00f, -1.00f, 0.00f, 1.00f, 1.00f, 0.00f, -1.00f, 1.00f, 0.00f }; GLubyte indices[][6] = { { 0, 1, 2, 0, 2, 3 }, // Quad #0 { 4, 5, 6, 4, 6, 7 }, // Quad #1 { 8, 9, 10, 8, 10, 11 }, // Quad #2 { 12, 13, 14, 12, 14, 15 }, // Quad #3 { 16, 17, 18, 16, 18, 19 } // Big Quad }; #define NumTests 4 GLfloat colors[NumTests][4] = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 0.0f, 0.0f } }; GLint numStencilBits; GLuint stencilValues[NumTests] = { 0x7, // Result of test 0 0x0, // Result of test 1 0x2, // Result of test 2 0xff // Result of test 3. We need to fill this // value in a run-time }; // Set the viewport glViewport ( 0, 0, esContext->width, esContext->height ); // Clear the color, depth, and stencil buffers. At this // point, the stencil buffer will be 0x1 for all pixels glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); // Use the program object glUseProgram ( userData->programObject ); // Load the vertex position glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, GL_FALSE, 0, vVertices ); glEnableVertexAttribArray ( userData->positionLoc ); // Test 0: // // Initialize upper-left region. In this case, the // stencil-buffer values will be replaced because the // stencil test for the rendered pixels will fail the // stencil test, which is // // ref mask stencil mask // ( 0x7 & 0x3 ) < ( 0x1 & 0x7 ) // // The value in the stencil buffer for these pixels will // be 0x7. // glStencilFunc( GL_LESS, 0x7, 0x3 ); glStencilOp( GL_REPLACE, GL_DECR, GL_DECR ); glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[0] ); // Test 1: // // Initialize the upper-right region. Here, we'll decrement // the stencil-buffer values where the stencil test passes // but the depth test fails. The stencil test is // // ref mask stencil mask // ( 0x3 & 0x3 ) > ( 0x1 & 0x3 ) // // but where the geometry fails the depth test. The // stencil values for these pixels will be 0x0. // glStencilFunc( GL_GREATER, 0x3, 0x3 ); glStencilOp( GL_KEEP, GL_DECR, GL_KEEP ); glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[1] ); // Test 2: // // Initialize the lower-left region. Here we'll increment // (with saturation) the stencil value where both the // stencil and depth tests pass. The stencil test for // these pixels will be // // ref mask stencil mask // ( 0x1 & 0x3 ) == ( 0x1 & 0x3 ) // // The stencil values for these pixels will be 0x2. // glStencilFunc( GL_EQUAL, 0x1, 0x3 ); glStencilOp( GL_KEEP, GL_INCR, GL_INCR ); glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[2] ); // Test 3: // // Finally, initialize the lower-right region. We'll invert // the stencil value where the stencil tests fails. The // stencil test for these pixels will be // // ref mask stencil mask // ( 0x2 & 0x1 ) == ( 0x1 & 0x1 ) // // The stencil value here will be set to ~((2^s-1) & 0x1), // (with the 0x1 being from the stencil clear value), // where 's' is the number of bits in the stencil buffer // glStencilFunc( GL_EQUAL, 0x2, 0x1 ); glStencilOp( GL_INVERT, GL_KEEP, GL_KEEP ); glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[3] ); // Since we don't know at compile time how many stecil bits are present, // we'll query, and update the value correct value in the // stencilValues arrays for the fourth tests. We'll use this value // later in rendering. glGetIntegerv( GL_STENCIL_BITS, &numStencilBits ); stencilValues[3] = ~(((1 << numStencilBits) - 1) & 0x1) & 0xff; // Use the stencil buffer for controlling where rendering will // occur. We diable writing to the stencil buffer so we // can test against them without modifying the values we // generated. glStencilMask( 0x0 ); for ( i = 0; i < NumTests; ++i ) { glStencilFunc( GL_EQUAL, stencilValues[i], 0xff ); glUniform4fv( userData->colorLoc, 1, colors[i] ); glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[4] ); } eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface ); }
void OGLRenderState::apply(const RenderState& _stateCaptured) noexcept { const auto& blendState = this->getBlendState(); const auto& rasterState = this->getRasterState(); const auto& depthState = this->getDepthState(); const auto& stencilState = this->getStencilState(); auto& _blendState = _stateCaptured.getBlendState(); auto& _rasterState = _stateCaptured.getRasterState(); auto& _depthState = _stateCaptured.getDepthState(); auto& _stencilState = _stateCaptured.getStencilState(); if (blendState.blendEnable) { if (!_blendState.blendEnable) { #if _USE_RENDER_COMMAND BlendEnableCommand command; command.header = GL_BLEND_ENABLE_COMMAND; _renderCommands.write(&command, sizeof(command)); #else glEnable(GL_BLEND); #endif } if (blendState.blendSeparateEnable) { if (_blendState.blendSrc != blendState.blendSrc || _blendState.blendDest != blendState.blendDest || _blendState.blendAlphaSrc != blendState.blendAlphaSrc || _blendState.blendAlphaDest != blendState.blendAlphaDest) { GLenum sfactorRGB = OGLTypes::asBlendFactor(blendState.blendSrc); GLenum dfactorRGB = OGLTypes::asBlendFactor(blendState.blendDest); GLenum sfactorAlpha = OGLTypes::asBlendFactor(blendState.blendAlphaSrc); GLenum dfactorAlpha = OGLTypes::asBlendFactor(blendState.blendAlphaDest); glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); } if (_blendState.blendOp != blendState.blendOp || _blendState.blendAlphaOp != blendState.blendAlphaOp) { GLenum modeRGB = OGLTypes::asBlendOperation(blendState.blendOp); GLenum modeAlpha = OGLTypes::asBlendOperation(blendState.blendAlphaOp); glBlendEquationSeparate(modeRGB, modeAlpha); } } else { if (_blendState.blendSrc != blendState.blendSrc || _blendState.blendDest != blendState.blendDest) { GLenum sfactorRGB = OGLTypes::asBlendFactor(blendState.blendSrc); GLenum dfactorRGB = OGLTypes::asBlendFactor(blendState.blendDest); glBlendFunc(sfactorRGB, dfactorRGB); } if (_blendState.blendOp != blendState.blendOp) { GLenum modeRGB = OGLTypes::asBlendOperation(blendState.blendOp); glBlendEquation(modeRGB); } } } else { if (_blendState.blendEnable) { glDisable(GL_BLEND); } } if (_rasterState.cullMode != rasterState.cullMode) { if (rasterState.cullMode != GPU_CULL_NONE) { GLenum mode = OGLTypes::asCullMode(rasterState.cullMode); glEnable(GL_CULL_FACE); glCullFace(mode); } else { glDisable(GL_CULL_FACE); } } #if !defined(EGLAPI) if (_rasterState.fillMode != rasterState.fillMode) { GLenum mode = OGLTypes::asFillMode(rasterState.fillMode); glPolygonMode(GL_FRONT_AND_BACK, mode); } #endif if (_rasterState.scissorTestEnable != rasterState.scissorTestEnable) { if (rasterState.scissorTestEnable) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); } if (_rasterState.srgbEnable != rasterState.srgbEnable) { if (rasterState.srgbEnable) glEnable(GL_FRAMEBUFFER_SRGB); else glDisable(GL_FRAMEBUFFER_SRGB); } if (depthState.depthEnable) { if (!_depthState.depthEnable) { glEnable(GL_DEPTH_TEST); } if (_depthState.depthFunc != depthState.depthFunc) { GLenum func = OGLTypes::asCompareFunction(depthState.depthFunc); glDepthFunc(func); } } else { if (_depthState.depthEnable) { glDisable(GL_DEPTH_TEST); } } if (_depthState.depthWriteMask != depthState.depthWriteMask) { GLboolean enable = depthState.depthWriteMask ? GL_TRUE : GL_FALSE; glDepthMask(enable); } if (depthState.depthBiasEnable) { if (!_depthState.depthBiasEnable) { glEnable(GL_POLYGON_OFFSET_FILL); } if (_depthState.depthBias != depthState.depthBias || _depthState.depthSlopScaleBias != depthState.depthSlopScaleBias) { glPolygonOffset(depthState.depthSlopScaleBias, depthState.depthBias); } } else { if (_depthState.depthBiasEnable) { glDisable(GL_POLYGON_OFFSET_FILL); } } if (stencilState.stencilEnable) { if (!_stencilState.stencilEnable) { glEnable(GL_STENCIL_TEST); } if (stencilState.stencilTwoEnable) { if (_stencilState.stencilFunc != stencilState.stencilFunc || _stencilState.stencilRef != stencilState.stencilRef || _stencilState.stencilReadMask != stencilState.stencilReadMask) { GLenum frontfunc = OGLTypes::asCompareFunction(stencilState.stencilFunc); glStencilFuncSeparate(GL_FRONT, frontfunc, stencilState.stencilRef, stencilState.stencilReadMask); GLenum backfunc = OGLTypes::asCompareFunction(stencilState.stencilTwoFunc); glStencilFuncSeparate(GL_BACK, backfunc, stencilState.stencilRef, stencilState.stencilTwoReadMask); } if (_stencilState.stencilFail != _stencilState.stencilFail || _stencilState.stencilZFail != _stencilState.stencilZFail || _stencilState.stencilPass != _stencilState.stencilPass) { GLenum frontfail = OGLTypes::asStencilOperation(_stencilState.stencilFail); GLenum frontzfail = OGLTypes::asStencilOperation(_stencilState.stencilZFail); GLenum frontpass = OGLTypes::asStencilOperation(_stencilState.stencilPass); glStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontpass); GLenum backfail = OGLTypes::asStencilOperation(_stencilState.stencilTwoFail); GLenum backzfail = OGLTypes::asStencilOperation(_stencilState.stencilTwoZFail); GLenum backpass = OGLTypes::asStencilOperation(_stencilState.stencilTwoPass); glStencilOpSeparate(GL_BACK, backfail, backzfail, backpass); } if (_stencilState.stencilWriteMask != stencilState.stencilWriteMask || _stencilState.stencilTwoWriteMask != stencilState.stencilTwoWriteMask) { glStencilMaskSeparate(GL_FRONT, stencilState.stencilWriteMask); glStencilMaskSeparate(GL_BACK, stencilState.stencilTwoWriteMask); } } else { if (_stencilState.stencilFunc != stencilState.stencilFunc || _stencilState.stencilRef != stencilState.stencilRef || _stencilState.stencilReadMask != stencilState.stencilReadMask) { GLenum func = OGLTypes::asCompareFunction(stencilState.stencilFunc); glStencilFunc(func, stencilState.stencilRef, stencilState.stencilReadMask); } if (_stencilState.stencilFail != stencilState.stencilFail || _stencilState.stencilZFail != stencilState.stencilZFail || _stencilState.stencilPass != stencilState.stencilPass) { GLenum fail = OGLTypes::asStencilOperation(stencilState.stencilFail); GLenum zfail = OGLTypes::asStencilOperation(stencilState.stencilZFail); GLenum pass = OGLTypes::asStencilOperation(stencilState.stencilPass); glStencilOp(fail, zfail, pass); } if (_stencilState.stencilWriteMask != stencilState.stencilWriteMask) { glStencilMask(stencilState.stencilWriteMask); } } } else { if (_stencilState.stencilEnable) { glDisable(GL_STENCIL_TEST); } } }
/////////////////////////////////////////////////////////////////////////////// // Render the block void RenderBlock(void) { GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f}; GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f }; switch(nStep) { // Wire frame case 0: glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vRed); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glDisable(GL_CULL_FACE); // Draw the cube cubeBatch.Draw(); break; // Wire frame, but not the back side... we also want the block to be in the stencil buffer case 1: shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vRed); // Draw solid block in stencil buffer // Back face culling prevents the back sides from showing through // The stencil pattern is used to mask when we draw the floor under it // to keep it from showing through. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_NEVER, 0, 0); glStencilOp(GL_INCR, GL_INCR, GL_INCR); cubeBatch.Draw(); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glDisable(GL_STENCIL_TEST); glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Draw the front side cube cubeBatch.Draw(); break; // Solid case 2: shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vRed); // Draw the cube cubeBatch.Draw(); break; // Lit case 3: shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, modelViewMatrix.GetMatrix(), projectionMatrix.GetMatrix(), vLightPos, vRed); // Draw the cube cubeBatch.Draw(); break; // Textured & Lit case 4: case 5: default: glBindTexture(GL_TEXTURE_2D, textures[2]); shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF, modelViewMatrix.GetMatrix(), projectionMatrix.GetMatrix(), vLightPos, vWhite, 0); glBindTexture(GL_TEXTURE_2D, textures[1]); topBlock.Draw(); glBindTexture(GL_TEXTURE_2D, textures[2]); frontBlock.Draw(); glBindTexture(GL_TEXTURE_2D, textures[3]); leftBlock.Draw(); break; } // Put everything back glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_CULL_FACE); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); glDisable(GL_STENCIL_TEST); }
void CLAYERS_OGL_DISP_LISTS::DrawAllCameraCulledSubtractLayer( const CLAYERS_OGL_DISP_LISTS *aLayerToSubtractA, const CLAYERS_OGL_DISP_LISTS *aLayerToSubtractB, bool aDrawMiddle ) const { if( aDrawMiddle ) DrawMiddle(); glClearStencil( 0x00 ); glClear( GL_STENCIL_BUFFER_BIT ); glEnable( GL_CULL_FACE ); glCullFace( GL_BACK ); glDisable( GL_DEPTH_TEST ); glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); glDepthMask( GL_FALSE ); glEnable( GL_STENCIL_TEST ); glStencilFunc( GL_ALWAYS, 1, 0 ); glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE ); if( aLayerToSubtractA ) aLayerToSubtractA->DrawBot(); if( aLayerToSubtractB ) aLayerToSubtractB->DrawBot(); //if( !m_draw_it_transparent ) { glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); } glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); glStencilFunc( GL_EQUAL, 0, 1 ); glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); DrawBot(); glDisable( GL_DEPTH_TEST ); glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); glDepthMask( GL_FALSE ); glEnable( GL_STENCIL_TEST ); glStencilFunc( GL_ALWAYS, 2, 0 ); glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE ); if( aLayerToSubtractA ) aLayerToSubtractA->DrawTop(); if( aLayerToSubtractB ) aLayerToSubtractB->DrawTop(); //if( !m_draw_it_transparent ) { glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); } glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); glStencilFunc( GL_NOTEQUAL, 2, 0x03 ); glStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); DrawTop(); glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE ); glCullFace( GL_FRONT ); glStencilFunc( GL_GEQUAL, 3, 0x03 ); glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); if( aDrawMiddle ) { if( aLayerToSubtractA ) aLayerToSubtractA->DrawMiddle(); // It will not render the middle contours of the layer. // It is used with vias and holes (copper vias and to subtract solder // mask holes). But since in the vias, it will draw a cylinder // and in soldermask it doesn't need to draw the contour. // so it is not used the middle part of B // if( aLayerToSubtractB ) // aLayerToSubtractB->DrawMiddle(); } glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE ); glCullFace( GL_BACK ); glDisable( GL_STENCIL_TEST ); /* if( m_draw_it_transparent ) { glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); }*/ }
static void redraw(void) { int start = 0, end; if (reportSpeed) { start = glutGet(GLUT_ELAPSED_TIME); } /* Clear; default stencil clears to zero. */ if ((stencilReflection && renderReflection) || (stencilShadow && renderShadow) || (haloScale > 1.0)) { glStencilMask(0xffffffff); glClearStencil(0x4); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } else { /* Avoid clearing stencil when not using it. */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } /* Reposition the light source. */ lightPosition[0] = 15*cos(lightAngle); lightPosition[1] = lightHeight; lightPosition[2] = 15*sin(lightAngle); if (directionalLight) { lightPosition[3] = 0.0; } else { lightPosition[3] = 1.0; } shadowMatrix(floorShadow, floorPlane, lightPosition); glPushMatrix(); /* Perform scene rotations based on user mouse input. */ glRotatef(angle2, 1.0, 0.0, 0.0); glRotatef(angle, 0.0, 1.0, 0.0); /* Tell GL new light source position. */ glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); if (renderReflection) { if (stencilReflection) { /* We can eliminate the visual "artifact" of seeing the "flipped" model underneath the floor by using stencil. The idea is draw the floor without color or depth update but so that a stencil value of one is where the floor will be. Later when rendering the model reflection, we will only update pixels with a stencil value of 1 to make sure the reflection only lives on the floor, not below the floor. */ /* Don't update color or depth. */ glDisable(GL_DEPTH_TEST); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); /* Draw 1 into the stencil buffer. */ glEnable(GL_STENCIL_TEST); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilFunc(GL_ALWAYS, 1, 0x1); glStencilMask(0x1); /* Now render floor; floor pixels just get their stencil set to 1. */ drawFloor(); /* Re-enable update of color and depth. */ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glEnable(GL_DEPTH_TEST); /* Now, only render where stencil is set to 1. */ glStencilFunc(GL_EQUAL, 1, 0x1); /* draw if ==1 */ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); } glPushMatrix(); /* The critical reflection step: Reflect 3D model through the floor (the Y=0 plane) to make a relection. */ glScalef(1.0, -1.0, 1.0); /* Reflect the light position. */ glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); /* To avoid our normals getting reversed and hence botched lighting on the reflection, turn on normalize. */ glEnable(GL_NORMALIZE); glCullFace(GL_FRONT); /* Draw the reflected model. */ glPushMatrix(); glTranslatef(0, 8.01, 0); drawModel(); glPopMatrix(); drawPillar(); /* Disable noramlize again and re-enable back face culling. */ glDisable(GL_NORMALIZE); glCullFace(GL_BACK); glPopMatrix(); /* Switch back to the unreflected light position. */ glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); if (stencilReflection) { glDisable(GL_STENCIL_TEST); } } /* Back face culling will get used to only draw either the top or the bottom floor. This let's us get a floor with two distinct appearances. The top floor surface is reflective and kind of red. The bottom floor surface is not reflective and blue. */ /* Draw "bottom" of floor in blue. */ glFrontFace(GL_CW); /* Switch face orientation. */ glColor4f(0.1, 0.1, 0.7, 1.0); drawFloor(); glFrontFace(GL_CCW); if (renderShadow && stencilShadow) { /* Draw the floor with stencil value 2. This helps us only draw the shadow once per floor pixel (and only on the floor pixels). */ glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 0x2, 0x2); glStencilMask(0x2); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); } /* Draw "top" of floor. Use blending to blend in reflection. */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(1.0, 1.0, 1.0, 0.3); drawFloor(); glDisable(GL_BLEND); if (renderShadow && stencilShadow) { glDisable(GL_STENCIL_TEST); } if (renderDinosaur) { drawPillar(); if (haloScale > 1.0) { /* If halo effect is enabled, draw the model with its stencil set to 6 (arbitary value); later, we'll make sure not to update pixels tagged as 6. */ glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 0x0, 0x4); glStencilMask(0x4); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); } /* Draw "actual" dinosaur (or other model), not its reflection. */ glPushMatrix(); glTranslatef(0, 8.01, 0); drawModel(); glPopMatrix(); } /* Begin shadow render. */ if (renderShadow) { /* Render the projected shadow. */ if (stencilShadow) { /* Now, only render where stencil is set above 5 (ie, 6 where the top floor is). Update stencil with 2 where the shadow gets drawn so we don't redraw (and accidently reblend) the shadow). */ glEnable(GL_STENCIL_TEST); glStencilFunc(GL_NOTEQUAL, 0x0, 0x2); glStencilMask(0x2); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); } /* To eliminate depth buffer artifacts, we use polygon offset to raise the depth of the projected shadow slightly so that it does not depth buffer alias with the floor. */ if (offsetShadow) { switch (polygonOffsetVersion) { #if defined(GL_EXT_polygon_offset) && !defined(GL_VERSION_1_1) case EXTENSION: glEnable(GL_POLYGON_OFFSET_EXT); break; #endif #ifdef GL_VERSION_1_1 case ONE_DOT_ONE: glEnable(GL_POLYGON_OFFSET_FILL); break; #endif case MISSING: /* Oh well. */ break; } } /* Render 50% black shadow color on top of whatever the floor appareance is. */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_LIGHTING); /* Force the 50% black. */ glColor4f(0.0, 0.0, 0.0, 0.5); glPushMatrix(); /* Project the shadow. */ glMultMatrixf((GLfloat *) floorShadow); glPushMatrix(); glTranslatef(0, 8.01, 0); drawModel(); glPopMatrix(); drawPillar(); glPopMatrix(); glDisable(GL_BLEND); glEnable(GL_LIGHTING); if (offsetShadow) { switch (polygonOffsetVersion) { #if defined(GL_EXT_polygon_offset) && !defined(GL_VERSION_1_1) case EXTENSION: glDisable(GL_POLYGON_OFFSET_EXT); break; #endif #ifdef GL_VERSION_1_1 case ONE_DOT_ONE: glDisable(GL_POLYGON_OFFSET_FILL); break; #endif case MISSING: /* Oh well. */ break; } } if (stencilShadow) { glDisable(GL_STENCIL_TEST); } } /* End shadow render. */ /* Begin light source location render. */ glPushMatrix(); glDisable(GL_LIGHTING); glColor3f(1.0, 1.0, 0.0); if (directionalLight) { /* Draw an arrowhead. */ glDisable(GL_CULL_FACE); glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]); glRotatef(lightAngle * -180.0 / M_PI, 0, 1, 0); glRotatef(atan(lightHeight/12) * 180.0 / M_PI, 0, 0, 1); glBegin(GL_TRIANGLE_FAN); glVertex3f(0, 0, 0); glVertex3f(2, 1, 1); glVertex3f(2, -1, 1); glVertex3f(2, -1, -1); glVertex3f(2, 1, -1); glVertex3f(2, 1, 1); glEnd(); /* Draw a white line from light direction. */ glColor3f(1.0, 1.0, 1.0); glBegin(GL_LINES); glVertex3f(0.1, 0, 0); glVertex3f(5, 0, 0); glEnd(); glEnable(GL_CULL_FACE); } else { /* Draw a yellow ball at the light source. */ glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]); glutSolidSphere(1.0, 5, 5); } glEnable(GL_LIGHTING); glPopMatrix(); /* End light source location render. */ /* Add a halo effect around the 3D model. */ if (haloScale > 1.0) { glDisable(GL_LIGHTING); if (blendedHalo) { /* If we are doing a nice blended halo, enable blending and make sure we only blend a halo pixel once and that we do not draw to pixels tagged as 6 (where the model is). */ glEnable(GL_BLEND); glEnable(GL_STENCIL_TEST); glColor4f(0.8, 0.8, 0.0, 0.3); /* 30% sorta yellow. */ glStencilFunc(GL_EQUAL, 0x4, 0x4); glStencilMask(0x4); glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); } else { /* Be cheap; no blending. Just draw yellow halo but not updating pixels where the model is. We don't update stencil at all. */ glDisable(GL_BLEND); glEnable(GL_STENCIL_TEST); glColor3f(0.5, 0.5, 0.0); /* Half yellow. */ glStencilFunc(GL_EQUAL, 0x4, 0x4); glStencilMask(0x4); glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); } glPushMatrix(); glTranslatef(0, 8.01, 0); glScalef(haloScale, haloScale, haloScale); drawModel(); glPopMatrix(); if (blendedHalo) { glDisable(GL_BLEND); } glDisable(GL_STENCIL_TEST); glEnable(GL_LIGHTING); } /* End halo effect render. */ glPopMatrix(); if (reportSpeed) { glFinish(); end = glutGet(GLUT_ELAPSED_TIME); printf("Speed %.3g frames/sec (%d ms)\n", 1000.0/(end-start), end-start); } glutSwapBuffers(); }
void MapRenderer::draw(GameWorld* world, const MapInfo& mi) { renderer->pushDebugGroup("Map"); renderer->useProgram(rectProg); // World out the number of units per tile glm::vec2 worldSize(GAME_MAP_SIZE); const int mapBlockLine = 8; glm::vec2 tileSize = worldSize / (float)mapBlockLine; // Determine the scale to show the right number of world units on the screen float worldScale = mi.screenSize / mi.worldSize; auto proj = renderer->get2DProjection(); glm::mat4 view, model; renderer->setUniform(rectProg, "proj", proj); renderer->setUniform(rectProg, "model", glm::mat4()); renderer->setUniform(rectProg, "colour", glm::vec4(0.f, 0.f, 0.f, 1.f)); view = glm::translate(view, glm::vec3(mi.screenPosition, 0.f)); if (mi.clipToSize) { glBindVertexArray( circle.getVAOName() ); glBindTexture(GL_TEXTURE_2D, 0); glm::mat4 circleView = glm::scale(view, glm::vec3(mi.screenSize)); renderer->setUniform(rectProg, "view", circleView); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilMask(0xFF); glColorMask(0x00, 0x00, 0x00, 0x00); glDrawArrays(GL_TRIANGLE_FAN, 0, 182); glColorMask(0xFF, 0xFF, 0xFF, 0xFF); glStencilFunc(GL_EQUAL, 1, 0xFF); } view = glm::scale(view, glm::vec3(worldScale)); view = glm::rotate(view, mi.rotation, glm::vec3(0.f, 0.f, 1.f)); view = glm::translate(view, glm::vec3(glm::vec2(-1.f, 1.f) * mi.worldCenter, 0.f)); renderer->setUniform(rectProg, "view", view); glBindVertexArray( rect.getVAOName() ); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); // radar00 = -x, +y // incrementing in X, then Y int initX = -(mapBlockLine/2); int initY = -(mapBlockLine/2); for( int m = 0; m < MAP_BLOCK_SIZE; ++m ) { std::string num = (m < 10 ? "0" : ""); std::string name = "radar" + num + std::to_string(m); auto texture = world->data->textures[{name,""}]; glBindTexture(GL_TEXTURE_2D, texture->getName()); int mX = initX + (m % mapBlockLine); int mY = initY + (m / mapBlockLine); auto tc = glm::vec2(mX, mY) * tileSize + glm::vec2(tileSize/2.f); glm::mat4 tilemodel = model; tilemodel = glm::translate( tilemodel, glm::vec3( tc, 0.f ) ); tilemodel = glm::scale( tilemodel, glm::vec3( tileSize, 1.f ) ); renderer->setUniform(rectProg, "model", tilemodel); glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 ); } // From here on out we will work in screenspace renderer->setUniform(rectProg, "view", glm::mat4()); if (mi.clipToSize) { glDisable(GL_STENCIL_TEST); // We only need the outer ring if we're clipping. glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ONE, GL_ZERO); TextureData::Handle radarDisc = data->findTexture("radardisc"); glm::mat4 model; model = glm::translate(model, glm::vec3(mi.screenPosition, 0.0f)); model = glm::scale(model, glm::vec3(mi.screenSize*1.07)); renderer->setUniform(rectProg, "model", model); glBindTexture(GL_TEXTURE_2D, radarDisc->getName()); glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 ); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); } for(auto& blip : world->state->radarBlips) { glm::vec2 blippos( blip.second.coord ); if( blip.second.target > 0 ) { GameObject* object = world->getBlipTarget(blip.second); if( object ) { blippos = glm::vec2( object->getPosition() ); } } drawBlip(blippos, view, mi, blip.second.texture); } // Draw the player blip auto player = world->pedestrianPool.find(world->state->playerObject); if( player ) { glm::vec2 plyblip(player->getPosition()); float hdg = glm::roll(player->getRotation()); drawBlip(plyblip, view, mi, "radar_centre", mi.rotation - hdg); } drawBlip(mi.worldCenter + glm::vec2(0.f, mi.worldSize), view, mi, "radar_north", 0.f, 24.f); glBindVertexArray( 0 ); glBindTexture(GL_TEXTURE_2D, 0); glUseProgram(0); /// @TODO migrate to using the renderer renderer->invalidate(); renderer->popDebugGroup(); }
uintptr_t processFn(struct fnargs* args, char* parg) { uintptr_t ret = 0; switch (args->fn) { case glfnUNDEFINED: abort(); // bad glfn break; case glfnActiveTexture: glActiveTexture((GLenum)args->a0); break; case glfnAttachShader: glAttachShader((GLint)args->a0, (GLint)args->a1); break; case glfnBindAttribLocation: glBindAttribLocation((GLint)args->a0, (GLint)args->a1, (GLchar*)args->a2); break; case glfnBindBuffer: glBindBuffer((GLenum)args->a0, (GLuint)args->a1); break; case glfnBindFramebuffer: glBindFramebuffer((GLenum)args->a0, (GLint)args->a1); break; case glfnBindRenderbuffer: glBindRenderbuffer((GLenum)args->a0, (GLint)args->a1); break; case glfnBindTexture: glBindTexture((GLenum)args->a0, (GLint)args->a1); break; case glfnBlendColor: glBlendColor(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); break; case glfnBlendEquation: glBlendEquation((GLenum)args->a0); break; case glfnBlendEquationSeparate: glBlendEquationSeparate((GLenum)args->a0, (GLenum)args->a1); break; case glfnBlendFunc: glBlendFunc((GLenum)args->a0, (GLenum)args->a1); break; case glfnBlendFuncSeparate: glBlendFuncSeparate((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLenum)args->a3); break; case glfnBufferData: glBufferData((GLenum)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg, (GLenum)args->a2); break; case glfnBufferSubData: glBufferSubData((GLenum)args->a0, (GLint)args->a1, (GLsizeiptr)args->a2, (GLvoid*)parg); break; case glfnCheckFramebufferStatus: ret = glCheckFramebufferStatus((GLenum)args->a0); break; case glfnClear: glClear((GLenum)args->a0); break; case glfnClearColor: glClearColor(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); break; case glfnClearDepthf: glClearDepthf(*(GLfloat*)&args->a0); break; case glfnClearStencil: glClearStencil((GLint)args->a0); break; case glfnColorMask: glColorMask((GLboolean)args->a0, (GLboolean)args->a1, (GLboolean)args->a2, (GLboolean)args->a3); break; case glfnCompileShader: glCompileShader((GLint)args->a0); break; case glfnCompressedTexImage2D: glCompressedTexImage2D((GLenum)args->a0, (GLint)args->a1, (GLenum)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLsizeiptr)args->a6, (GLvoid*)parg); break; case glfnCompressedTexSubImage2D: glCompressedTexSubImage2D((GLenum)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLenum)args->a6, (GLsizeiptr)args->a7, (GLvoid*)parg); break; case glfnCopyTexImage2D: glCopyTexImage2D((GLenum)args->a0, (GLint)args->a1, (GLenum)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLint)args->a6, (GLint)args->a7); break; case glfnCopyTexSubImage2D: glCopyTexSubImage2D((GLenum)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLint)args->a6, (GLint)args->a7); break; case glfnCreateProgram: ret = glCreateProgram(); break; case glfnCreateShader: ret = glCreateShader((GLenum)args->a0); break; case glfnCullFace: glCullFace((GLenum)args->a0); break; case glfnDeleteBuffer: glDeleteBuffers(1, (const GLuint*)(&args->a0)); break; case glfnDeleteFramebuffer: glDeleteFramebuffers(1, (const GLuint*)(&args->a0)); break; case glfnDeleteProgram: glDeleteProgram((GLint)args->a0); break; case glfnDeleteRenderbuffer: glDeleteRenderbuffers(1, (const GLuint*)(&args->a0)); break; case glfnDeleteShader: glDeleteShader((GLint)args->a0); break; case glfnDeleteTexture: glDeleteTextures(1, (const GLuint*)(&args->a0)); break; case glfnDepthFunc: glDepthFunc((GLenum)args->a0); break; case glfnDepthMask: glDepthMask((GLboolean)args->a0); break; case glfnDepthRangef: glDepthRangef(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1); break; case glfnDetachShader: glDetachShader((GLint)args->a0, (GLint)args->a1); break; case glfnDisable: glDisable((GLenum)args->a0); break; case glfnDisableVertexAttribArray: glDisableVertexAttribArray((GLint)args->a0); break; case glfnDrawArrays: glDrawArrays((GLenum)args->a0, (GLint)args->a1, (GLint)args->a2); break; case glfnDrawElements: glDrawElements((GLenum)args->a0, (GLint)args->a1, (GLenum)args->a2, (void*)args->a3); break; case glfnEnable: glEnable((GLenum)args->a0); break; case glfnEnableVertexAttribArray: glEnableVertexAttribArray((GLint)args->a0); break; case glfnFinish: glFinish(); break; case glfnFlush: glFlush(); break; case glfnFramebufferRenderbuffer: glFramebufferRenderbuffer((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLint)args->a3); break; case glfnFramebufferTexture2D: glFramebufferTexture2D((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLint)args->a3, (GLint)args->a4); break; case glfnFrontFace: glFrontFace((GLenum)args->a0); break; case glfnGenBuffer: glGenBuffers(1, (GLuint*)&ret); break; case glfnGenFramebuffer: glGenFramebuffers(1, (GLuint*)&ret); break; case glfnGenRenderbuffer: glGenRenderbuffers(1, (GLuint*)&ret); break; case glfnGenTexture: glGenTextures(1, (GLuint*)&ret); break; case glfnGenerateMipmap: glGenerateMipmap((GLenum)args->a0); break; case glfnGetActiveAttrib: glGetActiveAttrib( (GLuint)args->a0, (GLuint)args->a1, (GLsizei)args->a2, NULL, (GLint*)&ret, (GLenum*)args->a3, (GLchar*)parg); break; case glfnGetActiveUniform: glGetActiveUniform( (GLuint)args->a0, (GLuint)args->a1, (GLsizei)args->a2, NULL, (GLint*)&ret, (GLenum*)args->a3, (GLchar*)parg); break; case glfnGetAttachedShaders: glGetAttachedShaders((GLuint)args->a0, (GLsizei)args->a1, (GLsizei*)&ret, (GLuint*)parg); break; case glfnGetAttribLocation: ret = glGetAttribLocation((GLint)args->a0, (GLchar*)args->a1); break; case glfnGetBooleanv: glGetBooleanv((GLenum)args->a0, (GLboolean*)parg); break; case glfnGetBufferParameteri: glGetBufferParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)&ret); break; case glfnGetFloatv: glGetFloatv((GLenum)args->a0, (GLfloat*)parg); break; case glfnGetIntegerv: glGetIntegerv((GLenum)args->a0, (GLint*)parg); break; case glfnGetError: ret = glGetError(); break; case glfnGetFramebufferAttachmentParameteriv: glGetFramebufferAttachmentParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLint*)&ret); break; case glfnGetProgramiv: glGetProgramiv((GLint)args->a0, (GLenum)args->a1, (GLint*)&ret); break; case glfnGetProgramInfoLog: glGetProgramInfoLog((GLuint)args->a0, (GLsizei)args->a1, 0, (GLchar*)parg); break; case glfnGetRenderbufferParameteriv: glGetRenderbufferParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)&ret); break; case glfnGetShaderiv: glGetShaderiv((GLint)args->a0, (GLenum)args->a1, (GLint*)&ret); break; case glfnGetShaderInfoLog: glGetShaderInfoLog((GLuint)args->a0, (GLsizei)args->a1, 0, (GLchar*)parg); break; case glfnGetShaderPrecisionFormat: glGetShaderPrecisionFormat((GLenum)args->a0, (GLenum)args->a1, (GLint*)parg, &((GLint*)parg)[2]); break; case glfnGetShaderSource: glGetShaderSource((GLuint)args->a0, (GLsizei)args->a1, 0, (GLchar*)parg); break; case glfnGetString: ret = (uintptr_t)glGetString((GLenum)args->a0); break; case glfnGetTexParameterfv: glGetTexParameterfv((GLenum)args->a0, (GLenum)args->a1, (GLfloat*)parg); break; case glfnGetTexParameteriv: glGetTexParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)parg); break; case glfnGetUniformfv: glGetUniformfv((GLuint)args->a0, (GLint)args->a1, (GLfloat*)parg); break; case glfnGetUniformiv: glGetUniformiv((GLuint)args->a0, (GLint)args->a1, (GLint*)parg); break; case glfnGetUniformLocation: ret = glGetUniformLocation((GLint)args->a0, (GLchar*)args->a1); break; case glfnGetVertexAttribfv: glGetVertexAttribfv((GLuint)args->a0, (GLenum)args->a1, (GLfloat*)parg); break; case glfnGetVertexAttribiv: glGetVertexAttribiv((GLuint)args->a0, (GLenum)args->a1, (GLint*)parg); break; case glfnHint: glHint((GLenum)args->a0, (GLenum)args->a1); break; case glfnIsBuffer: ret = glIsBuffer((GLint)args->a0); break; case glfnIsEnabled: ret = glIsEnabled((GLenum)args->a0); break; case glfnIsFramebuffer: ret = glIsFramebuffer((GLint)args->a0); break; case glfnIsProgram: ret = glIsProgram((GLint)args->a0); break; case glfnIsRenderbuffer: ret = glIsRenderbuffer((GLint)args->a0); break; case glfnIsShader: ret = glIsShader((GLint)args->a0); break; case glfnIsTexture: ret = glIsTexture((GLint)args->a0); break; case glfnLineWidth: glLineWidth(*(GLfloat*)&args->a0); break; case glfnLinkProgram: glLinkProgram((GLint)args->a0); break; case glfnPixelStorei: glPixelStorei((GLenum)args->a0, (GLint)args->a1); break; case glfnPolygonOffset: glPolygonOffset(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1); break; case glfnReadPixels: glReadPixels((GLint)args->a0, (GLint)args->a1, (GLsizei)args->a2, (GLsizei)args->a3, (GLenum)args->a4, (GLenum)args->a5, (void*)parg); break; case glfnReleaseShaderCompiler: glReleaseShaderCompiler(); break; case glfnRenderbufferStorage: glRenderbufferStorage((GLenum)args->a0, (GLenum)args->a1, (GLint)args->a2, (GLint)args->a3); break; case glfnSampleCoverage: glSampleCoverage(*(GLfloat*)&args->a0, (GLboolean)args->a1); break; case glfnScissor: glScissor((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3); break; case glfnShaderSource: #if defined(os_ios) || defined(os_osx) glShaderSource((GLuint)args->a0, (GLsizei)args->a1, (const GLchar *const *)args->a2, NULL); #else glShaderSource((GLuint)args->a0, (GLsizei)args->a1, (const GLchar **)args->a2, NULL); #endif break; case glfnStencilFunc: glStencilFunc((GLenum)args->a0, (GLint)args->a1, (GLuint)args->a2); break; case glfnStencilFuncSeparate: glStencilFuncSeparate((GLenum)args->a0, (GLenum)args->a1, (GLint)args->a2, (GLuint)args->a3); break; case glfnStencilMask: glStencilMask((GLuint)args->a0); break; case glfnStencilMaskSeparate: glStencilMaskSeparate((GLenum)args->a0, (GLuint)args->a1); break; case glfnStencilOp: glStencilOp((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2); break; case glfnStencilOpSeparate: glStencilOpSeparate((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLenum)args->a3); break; case glfnTexImage2D: glTexImage2D( (GLenum)args->a0, (GLint)args->a1, (GLint)args->a2, (GLsizei)args->a3, (GLsizei)args->a4, 0, // border (GLenum)args->a5, (GLenum)args->a6, (const GLvoid*)parg); break; case glfnTexSubImage2D: glTexSubImage2D( (GLenum)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLsizei)args->a4, (GLsizei)args->a5, (GLenum)args->a6, (GLenum)args->a7, (const GLvoid*)parg); break; case glfnTexParameterf: glTexParameterf((GLenum)args->a0, (GLenum)args->a1, *(GLfloat*)&args->a2); break; case glfnTexParameterfv: glTexParameterfv((GLenum)args->a0, (GLenum)args->a1, (GLfloat*)parg); break; case glfnTexParameteri: glTexParameteri((GLenum)args->a0, (GLenum)args->a1, (GLint)args->a2); break; case glfnTexParameteriv: glTexParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)parg); break; case glfnUniform1f: glUniform1f((GLint)args->a0, *(GLfloat*)&args->a1); break; case glfnUniform1fv: glUniform1fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniform1i: glUniform1i((GLint)args->a0, (GLint)args->a1); break; case glfnUniform1iv: glUniform1iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniform2f: glUniform2f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2); break; case glfnUniform2fv: glUniform2fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniform2i: glUniform2i((GLint)args->a0, (GLint)args->a1, (GLint)args->a2); break; case glfnUniform2iv: glUniform2iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniform3f: glUniform3f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); break; case glfnUniform3fv: glUniform3fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniform3i: glUniform3i((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3); break; case glfnUniform3iv: glUniform3iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniform4f: glUniform4f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3, *(GLfloat*)&args->a4); break; case glfnUniform4fv: glUniform4fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniform4i: glUniform4i((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4); break; case glfnUniform4iv: glUniform4iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniformMatrix2fv: glUniformMatrix2fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); break; case glfnUniformMatrix3fv: glUniformMatrix3fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); break; case glfnUniformMatrix4fv: glUniformMatrix4fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); break; case glfnUseProgram: glUseProgram((GLint)args->a0); break; case glfnValidateProgram: glValidateProgram((GLint)args->a0); break; case glfnVertexAttrib1f: glVertexAttrib1f((GLint)args->a0, *(GLfloat*)&args->a1); break; case glfnVertexAttrib1fv: glVertexAttrib1fv((GLint)args->a0, (GLfloat*)parg); break; case glfnVertexAttrib2f: glVertexAttrib2f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2); break; case glfnVertexAttrib2fv: glVertexAttrib2fv((GLint)args->a0, (GLfloat*)parg); break; case glfnVertexAttrib3f: glVertexAttrib3f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); break; case glfnVertexAttrib3fv: glVertexAttrib3fv((GLint)args->a0, (GLfloat*)parg); break; case glfnVertexAttrib4f: glVertexAttrib4f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3, *(GLfloat*)&args->a4); break; case glfnVertexAttrib4fv: glVertexAttrib4fv((GLint)args->a0, (GLfloat*)parg); break; case glfnVertexAttribPointer: glVertexAttribPointer((GLuint)args->a0, (GLint)args->a1, (GLenum)args->a2, (GLboolean)args->a3, (GLsizei)args->a4, (const GLvoid*)args->a5); break; case glfnViewport: glViewport((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3); break; } return ret; }
static void pie_DrawShadows(void) { const float width = pie_GetVideoBufferWidth(); const float height = pie_GetVideoBufferHeight(); GLenum op_depth_pass_front = GL_INCR, op_depth_pass_back = GL_DECR; pie_SetTexturePage(TEXPAGE_NONE); glPushMatrix(); pie_SetAlphaTest(false); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthFunc(GL_LESS); glDepthMask(GL_FALSE); glEnable(GL_STENCIL_TEST); // Check if we have the required extensions if (GLEW_EXT_stencil_wrap) { op_depth_pass_front = GL_INCR_WRAP_EXT; op_depth_pass_back = GL_DECR_WRAP_EXT; } // generic 1-pass version if (GLEW_EXT_stencil_two_side) { glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); glDisable(GL_CULL_FACE); glStencilMask(~0); glActiveStencilFaceEXT(GL_BACK); glStencilOp(GL_KEEP, GL_KEEP, op_depth_pass_back); glStencilFunc(GL_ALWAYS, 0, ~0); glActiveStencilFaceEXT(GL_FRONT); glStencilOp(GL_KEEP, GL_KEEP, op_depth_pass_front); glStencilFunc(GL_ALWAYS, 0, ~0); pie_ShadowDrawLoop(); glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); } // check for ATI-specific 1-pass version else if (GLEW_ATI_separate_stencil) { glDisable(GL_CULL_FACE); glStencilMask(~0); glStencilOpSeparateATI(GL_BACK, GL_KEEP, GL_KEEP, op_depth_pass_back); glStencilOpSeparateATI(GL_FRONT, GL_KEEP, GL_KEEP, op_depth_pass_front); glStencilFunc(GL_ALWAYS, 0, ~0); pie_ShadowDrawLoop(); } // fall back to default 2-pass version else { glStencilMask(~0); glStencilFunc(GL_ALWAYS, 0, ~0); glEnable(GL_CULL_FACE); // Setup stencil for front-facing polygons glCullFace(GL_BACK); glStencilOp(GL_KEEP, GL_KEEP, op_depth_pass_front); pie_ShadowDrawLoop(); // Setup stencil for back-facing polygons glCullFace(GL_FRONT); glStencilOp(GL_KEEP, GL_KEEP, op_depth_pass_back); pie_ShadowDrawLoop(); } pie_SetRendMode(REND_ALPHA); glEnable(GL_CULL_FACE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilMask(~0); glStencilFunc(GL_LESS, 0, ~0); glColor4f(0, 0, 0, 0.5); pie_PerspectiveEnd(); glLoadIdentity(); glDisable(GL_DEPTH_TEST); glBegin(GL_TRIANGLE_STRIP); glVertex2f(0, 0); glVertex2f(width, 0); glVertex2f(0, height); glVertex2f(width, height); glEnd(); pie_PerspectiveBegin(); pie_SetRendMode(REND_OPAQUE); glDisable(GL_STENCIL_TEST); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glPopMatrix(); nb_scshapes = 0; }
/* ==================== RE_BeginFrame If running in stereo, RE_BeginFrame will be called twice for each RE_EndFrame ==================== */ void RE_BeginFrame(stereoFrame_t stereoFrame) { drawBufferCommand_t *cmd; if (!tr.registered) { return; } GLimp_LogComment("--- RE_BeginFrame ---\n"); #if defined(USE_D3D10) // TODO #else glState.finishCalled = qfalse; #endif tr.frameCount++; tr.frameSceneNum = 0; tr.viewCount = 0; #if defined(USE_D3D10) // draw buffer stuff cmd = (drawBufferCommand_t *)R_GetCommandBuffer(sizeof(*cmd)); if (!cmd) { return; } cmd->commandId = RC_DRAW_BUFFER; cmd->buffer = 0; #else // do overdraw measurement if (r_measureOverdraw->integer) { if (glConfig.stencilBits < 4) { ri.Printf(PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits); ri.Cvar_Set("r_measureOverdraw", "0"); r_measureOverdraw->modified = qfalse; } else { R_SyncRenderThread(); glEnable(GL_STENCIL_TEST); glStencilMask(~0U); GL_ClearStencil(0U); glStencilFunc(GL_ALWAYS, 0U, ~0U); glStencilOp(GL_KEEP, GL_INCR, GL_INCR); } r_measureOverdraw->modified = qfalse; } else { // this is only reached if it was on and is now off if (r_measureOverdraw->modified) { R_SyncRenderThread(); glDisable(GL_STENCIL_TEST); } r_measureOverdraw->modified = qfalse; } // texturemode stuff if (r_textureMode->modified) { R_SyncRenderThread(); GL_TextureMode(r_textureMode->string); r_textureMode->modified = qfalse; } // gamma stuff if (r_gamma->modified) { r_gamma->modified = qfalse; if (!glConfig.deviceSupportsGamma) { Com_Printf("r_gamma will be changed upon restarting.\n"); } else { R_SyncRenderThread(); R_SetColorMappings(); } } // check for errors if (!r_ignoreGLErrors->integer) { int err; char s[128]; R_SyncRenderThread(); if ((err = glGetError()) != GL_NO_ERROR) { switch (err) { case GL_INVALID_ENUM: strcpy(s, "GL_INVALID_ENUM"); break; case GL_INVALID_VALUE: strcpy(s, "GL_INVALID_VALUE"); break; case GL_INVALID_OPERATION: strcpy(s, "GL_INVALID_OPERATION"); break; case GL_STACK_OVERFLOW: strcpy(s, "GL_STACK_OVERFLOW"); break; case GL_STACK_UNDERFLOW: strcpy(s, "GL_STACK_UNDERFLOW"); break; case GL_OUT_OF_MEMORY: strcpy(s, "GL_OUT_OF_MEMORY"); break; case GL_TABLE_TOO_LARGE: strcpy(s, "GL_TABLE_TOO_LARGE"); break; case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: strcpy(s, "GL_INVALID_FRAMEBUFFER_OPERATION_EXT"); break; default: Com_sprintf(s, sizeof(s), "0x%X", err); break; } //ri.Error(ERR_FATAL, "caught OpenGL error: %s in file %s line %i", s, filename, line); ri.Error(ERR_FATAL, "RE_BeginFrame() - glGetError() failed (%s)!\n", s); } } // draw buffer stuff cmd = (drawBufferCommand_t *)R_GetCommandBuffer(sizeof(*cmd)); if (!cmd) { return; } cmd->commandId = RC_DRAW_BUFFER; if (glConfig.stereoEnabled) { if (stereoFrame == STEREO_LEFT) { cmd->buffer = (int)GL_BACK_LEFT; } else if (stereoFrame == STEREO_RIGHT) { cmd->buffer = (int)GL_BACK_RIGHT; } else { ri.Error(ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame); } } else { if (stereoFrame != STEREO_CENTER) { ri.Error(ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame); } if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT")) { cmd->buffer = (int)GL_FRONT; } else { cmd->buffer = (int)GL_BACK; } } #endif }
void IrrDriver::renderGlow(std::vector<GlowData>& glows) { m_scene_manager->setCurrentRendertime(scene::ESNRP_SOLID); m_rtts->getFBO(FBO_TMP1_WITH_DS).bind(); glClearStencil(0); glClearColor(0, 0, 0, 0); glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); const u32 glowcount = (int)glows.size(); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilFunc(GL_ALWAYS, 1, ~0); glEnable(GL_STENCIL_TEST); glEnable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glDisable(GL_BLEND); if (CVS->isARBBaseInstanceUsable()) glBindVertexArray(VAOManager::getInstance()->getVAO(EVT_STANDARD)); for (u32 i = 0; i < glowcount; i++) { const GlowData &dat = glows[i]; scene::ISceneNode * cur = dat.node; STKMeshSceneNode *node = static_cast<STKMeshSceneNode *>(cur); node->setGlowColors(SColor(0, (unsigned) (dat.b * 255.f), (unsigned)(dat.g * 255.f), (unsigned)(dat.r * 255.f))); if (!CVS->supportsIndirectInstancingRendering()) node->render(); } if (CVS->supportsIndirectInstancingRendering()) { glBindBuffer(GL_DRAW_INDIRECT_BUFFER, GlowPassCmd::getInstance()->drawindirectcmd); InstancedColorizeShader::getInstance()->use(); glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeGlow)); if (CVS->isAZDOEnabled()) { if (GlowPassCmd::getInstance()->Size) { glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)(GlowPassCmd::getInstance()->Offset * sizeof(DrawElementsIndirectCommand)), (int)GlowPassCmd::getInstance()->Size, sizeof(DrawElementsIndirectCommand)); } } else { for (unsigned i = 0; i < ListInstancedGlow::getInstance()->size(); i++) glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((GlowPassCmd::getInstance()->Offset + i) * sizeof(DrawElementsIndirectCommand))); } } glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); // To half FrameBuffer::Blit(irr_driver->getFBO(FBO_TMP1_WITH_DS), irr_driver->getFBO(FBO_HALF1), GL_COLOR_BUFFER_BIT, GL_LINEAR); // To quarter FrameBuffer::Blit(irr_driver->getFBO(FBO_HALF1), irr_driver->getFBO(FBO_QUARTER1), GL_COLOR_BUFFER_BIT, GL_LINEAR); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glStencilFunc(GL_EQUAL, 0, ~0); glEnable(GL_STENCIL_TEST); m_rtts->getFBO(FBO_COLORS).bind(); m_post_processing->renderGlow(m_rtts->getRenderTarget(RTT_QUARTER1)); glDisable(GL_STENCIL_TEST); }
void DemoApplication::renderme() { myinit(); updateCamera(); if (m_dynamicsWorld) { if(m_enableshadows) { glClear(GL_STENCIL_BUFFER_BIT); glEnable(GL_CULL_FACE); renderscene(0); glDisable(GL_LIGHTING); glDepthMask(GL_FALSE); glDepthFunc(GL_LEQUAL); glEnable(GL_STENCIL_TEST); glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); glStencilFunc(GL_ALWAYS,1,0xFFFFFFFFL); glFrontFace(GL_CCW); glStencilOp(GL_KEEP,GL_KEEP,GL_INCR); renderscene(1); glFrontFace(GL_CW); glStencilOp(GL_KEEP,GL_KEEP,GL_DECR); renderscene(1); glFrontFace(GL_CCW); glPolygonMode(GL_FRONT,GL_FILL); glPolygonMode(GL_BACK,GL_FILL); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_LIGHTING); glDepthMask(GL_TRUE); glCullFace(GL_BACK); glFrontFace(GL_CCW); glEnable(GL_CULL_FACE); glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); glDepthFunc(GL_LEQUAL); glStencilFunc( GL_NOTEQUAL, 0, 0xFFFFFFFFL ); glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); glDisable(GL_LIGHTING); renderscene(2); glEnable(GL_LIGHTING); glDepthFunc(GL_LESS); glDisable(GL_STENCIL_TEST); glDisable(GL_CULL_FACE); } else { glDisable(GL_CULL_FACE); renderscene(0); } int xOffset = 10; int yStart = 20; int yIncr = 20; glDisable(GL_LIGHTING); glColor3f(0, 0, 0); if ((m_debugMode & btIDebugDraw::DBG_NoHelpText)==0) { setOrthographicProjection(); showInfo(xOffset,yStart,yIncr); //showProfileInfo(xOffset,yStart,yIncr); #ifdef USE_QUICKPROF if ( getDebugMode() & btIDebugDraw::DBG_ProfileTimings) { static int counter = 0; counter++; std::map<std::string, hidden::ProfileBlock*>::iterator iter; for (iter = btProfiler::mProfileBlocks.begin(); iter != btProfiler::mProfileBlocks.end(); ++iter) { char blockTime[128]; sprintf(blockTime, "%s: %lf",&((*iter).first[0]),btProfiler::getBlockTime((*iter).first, btProfiler::BLOCK_CYCLE_SECONDS));//BLOCK_TOTAL_PERCENT)); glRasterPos3f(xOffset,yStart,0); GLDebugDrawString(BMF_GetFont(BMF_kHelvetica10),blockTime); yStart += yIncr; } } #endif //USE_QUICKPROF resetPerspectiveProjection(); } glDisable(GL_LIGHTING); } updateCamera(); }
/// Called by OpenGL device to active this state block. /// @param oldState The current state, used to make sure we don't set redundant states on the device. Pass NULL to reset all states. void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState) { // Big scary warning copied from Apple docs // http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_performance/chapter_13_section_2.html#//apple_ref/doc/uid/TP40001987-CH213-SW12 // Don't set a state that's already set. Once a feature is enabled, it does not need to be enabled again. // Calling an enable function more than once does nothing except waste time because OpenGL does not check // the state of a feature when you call glEnable or glDisable. For instance, if you call glEnable(GL_LIGHTING) // more than once, OpenGL does not check to see if the lighting state is already enabled. It simply updates // the state value even if that value is identical to the current value. #define STATE_CHANGE(state) (!oldState || oldState->mDesc.state != mDesc.state) #define TOGGLE_STATE(state, enum) if(mDesc.state) glEnable(enum); else glDisable(enum) #define CHECK_TOGGLE_STATE(state, enum) if(!oldState || oldState->mDesc.state != mDesc.state) if(mDesc.state) glEnable(enum); else glDisable(enum) // Blending CHECK_TOGGLE_STATE(blendEnable, GL_BLEND); if(STATE_CHANGE(blendSrc) || STATE_CHANGE(blendDest)) glBlendFunc(GFXGLBlend[mDesc.blendSrc], GFXGLBlend[mDesc.blendDest]); if(STATE_CHANGE(blendOp)) glBlendEquation(GFXGLBlendOp[mDesc.blendOp]); // Color write masks if(STATE_CHANGE(colorWriteRed) || STATE_CHANGE(colorWriteBlue) || STATE_CHANGE(colorWriteGreen) || STATE_CHANGE(colorWriteAlpha)) glColorMask(mDesc.colorWriteRed, mDesc.colorWriteBlue, mDesc.colorWriteGreen, mDesc.colorWriteAlpha); // Culling if(STATE_CHANGE(cullMode)) { TOGGLE_STATE(cullMode, GL_CULL_FACE); glCullFace(GFXGLCullMode[mDesc.cullMode]); } // Depth CHECK_TOGGLE_STATE(zEnable, GL_DEPTH_TEST); if(STATE_CHANGE(zFunc)) glDepthFunc(GFXGLCmpFunc[mDesc.zFunc]); if(STATE_CHANGE(zBias)) { if (mDesc.zBias == 0) { glDisable(GL_POLYGON_OFFSET_FILL); } else { F32 bias = mDesc.zBias * 10000.0f; glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(bias, bias); } } if(STATE_CHANGE(zWriteEnable)) glDepthMask(mDesc.zWriteEnable); // Stencil CHECK_TOGGLE_STATE(stencilEnable, GL_STENCIL_TEST); if(STATE_CHANGE(stencilFunc) || STATE_CHANGE(stencilRef) || STATE_CHANGE(stencilMask)) glStencilFunc(GFXGLCmpFunc[mDesc.stencilFunc], mDesc.stencilRef, mDesc.stencilMask); if(STATE_CHANGE(stencilFailOp) || STATE_CHANGE(stencilZFailOp) || STATE_CHANGE(stencilPassOp)) glStencilOp(GFXGLStencilOp[mDesc.stencilFailOp], GFXGLStencilOp[mDesc.stencilZFailOp], GFXGLStencilOp[mDesc.stencilPassOp]); if(STATE_CHANGE(stencilWriteMask)) glStencilMask(mDesc.stencilWriteMask); if(STATE_CHANGE(fillMode)) glPolygonMode(GL_FRONT_AND_BACK, GFXGLFillMode[mDesc.fillMode]); #undef CHECK_STATE #undef TOGGLE_STATE #undef CHECK_TOGGLE_STATE //sampler objects if( gglHasExtension(ARB_sampler_objects) ) { for (U32 i = 0; i < getMin(getOwningDevice()->getNumSamplers(), (U32) TEXTURE_STAGE_COUNT); i++) { if(!oldState || oldState->mSamplerObjects[i] != mSamplerObjects[i]) glBindSampler(i, mSamplerObjects[i] ); } } // TODO: states added for detail blend }
void shadow_render_model(model_draw *draw) { int n,k,t,poly_count,trig_count; float f_dist; double dx,dy,dz,d_alpha; float *vp,*vertex_ptr,*vl,*cl; unsigned short *index_ptr; d3vct ray_move; d3pnt *spt,*ept,*hpt; model_trig_type *trig; model_mesh_type *mesh; model_type *mdl; view_light_spot_type *lspot; // get model mdl=model_find_uid(draw->uid); if (mdl==NULL) return; // find all polys the shadow ray hits poly_count=shadow_build_poly_set_model(mdl,draw); if (poly_count==0) return; // get light and draw distance lspot=shadow_get_light_spot(&draw->pnt,draw->size.y); f_dist=(float)lspot->intensity; // get distance alpha factor d_alpha=(double)lspot->intensity; d_alpha=1.0/(d_alpha*d_alpha); // start stenciling // never write to the depth buffer during this operation glEnable(GL_STENCIL_TEST); glDisable(GL_ALPHA_TEST); glDepthMask(GL_FALSE); // setup blending glColor4f(0.0f,0.0f,0.0f,1.0f); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // run through all the stenciled polygons // and ray trace against their planes // to create the shadow polygons for (k=0;k!=poly_count;k++) { // stencil the poly we are going // to draw a shadow on shadow_stencil_mesh_poly(shadow_poly_ptrs[k].mesh_idx,shadow_poly_ptrs[k].poly_idx); // shadows are blended and stenciled // we clear the stencil as we draw so // we can maintain the alpha levels glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); glStencilOp(GL_KEEP,GL_KEEP,GL_ZERO); glStencilFunc(GL_EQUAL,stencil_shadow,0xFF); // run through all the meshes of this model for (n=0;n!=mdl->nmesh;n++) { if ((draw->render_mesh_mask&(0x1<<n))==0) continue; // ray trace the mesh against // the plane of the polygon mesh=&mdl->meshes[n]; vp=draw->setup.mesh_arrays[n].gl_vertex_array; spt=shadow_spt; ept=shadow_ept; for (t=0;t!=mesh->nvertex;t++) { spt->x=(int)*vp++; spt->y=(int)*vp++; spt->z=(int)*vp++; vector_create(&ray_move,lspot->pnt.x,lspot->pnt.y,lspot->pnt.z,spt->x,spt->y,spt->z); ept->x=spt->x-(int)(ray_move.x*f_dist); ept->y=spt->y-(int)(ray_move.y*f_dist); ept->z=spt->z-(int)(ray_move.z*f_dist); spt++; ept++; } ray_trace_mesh_poly_plane(mesh->nvertex,shadow_spt,shadow_ept,shadow_hpt,shadow_hits,shadow_poly_ptrs[k].mesh_idx,shadow_poly_ptrs[k].poly_idx); // setup the vertex objects vertex_ptr=view_bind_map_next_vertex_object(mesh->nvertex*(3+4)); if (vertex_ptr==NULL) { glDisable(GL_STENCIL_TEST); glDepthMask(GL_TRUE); return; } vl=vertex_ptr; cl=vertex_ptr+(mesh->nvertex*3); // vertexes hpt=shadow_hpt; for (t=0;t!=mesh->nvertex;t++) { // vertex *vl++=(float)hpt->x; *vl++=(float)hpt->y; *vl++=(float)hpt->z; // color dx=(hpt->x-lspot->pnt.x); dy=(hpt->y-lspot->pnt.y); dz=(hpt->z-lspot->pnt.z); hpt++; *cl++=0.0f; *cl++=0.0f; *cl++=0.0f; *cl++=1.0f-(float)(((dx*dx)+(dy*dy)+(dz*dz))*d_alpha); } view_unmap_current_vertex_object(); // create the index object index_ptr=view_bind_map_next_index_object(mesh->ntrig*3); if (index_ptr==NULL) { view_unbind_current_vertex_object(); glDisable(GL_STENCIL_TEST); glDepthMask(GL_TRUE); return; } trig_count=0; trig=mesh->trigs; for (t=0;t!=mesh->ntrig;t++) { if ((shadow_hits[trig->v[0]]) && (shadow_hits[trig->v[1]]) && (shadow_hits[trig->v[2]])) { *index_ptr++=trig->v[0]; *index_ptr++=trig->v[1]; *index_ptr++=trig->v[2]; trig_count++; } trig++; } view_unmap_current_index_object(); // draw the shadow trigs glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3,GL_FLOAT,0,0); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4,GL_FLOAT,0,(void*)((mesh->nvertex*3)*sizeof(float))); glDrawRangeElements(GL_TRIANGLES,0,mesh->nvertex,(trig_count*3),GL_UNSIGNED_SHORT,(GLvoid*)0); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); // unbind the vertex and index object view_unbind_current_vertex_object(); view_unbind_current_index_object(); } shadow_stencil_clear_mesh_poly(); } // restore depth buffer and turn // off stenciling glDepthMask(GL_TRUE); glDisable(GL_STENCIL_TEST); }
void cContextMenu::draw(int xoffset, int yoffset) { xoffset += x_; yoffset += y_; // Enable stencil buffer glClear(GL_STENCIL_BUFFER_BIT); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_NEVER, 1, 1); glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP); // Simply write to the stencil buffer glDisable(GL_BLEND); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_EQUAL, 1.0f); float rightTexCoord = (float)width_ / 64.0f; float downTexCoord = (float)height_ / 64.0f; checkerboard->bind(); glBegin(GL_QUADS); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex2i(xoffset, yoffset); glTexCoord2f(rightTexCoord, 0.0f); glVertex2i(xoffset + width_, yoffset); glTexCoord2f(rightTexCoord, downTexCoord); glVertex2i(xoffset + width_, yoffset + height_); glTexCoord2f(0.0f, downTexCoord); glVertex2i(xoffset, yoffset + height_); glEnd(); glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_NOTEQUAL, 0, 0xff); border->draw(xoffset, yoffset); glDisable(GL_STENCIL_TEST); // Get mouse position QPoint pos = GLWidget->mapFromGlobal(QCursor::pos()); int x= pos.x(); int y = pos.y(); x -= xoffset; // Modify mouse coordinates y -= yoffset; // Modify mouse coordinates Iterator it; for (it = entries.begin(); it != entries.end(); ++it) { if (x >= 7 && x <= width_ - 7 && y >= (*it)->y() && y < (*it)->y() + (*it)->height()) { glDisable(GL_TEXTURE_2D); // Disable texturing. glBegin(GL_QUADS); glColor4f(0.5f, 0.5f, 0.5f, 1.0f); // Should be a shade of gray int left = xoffset + 7; int top = yoffset + (*it)->y() + 2; glVertex2i(left, top); glVertex2i(left + width_ - 12, top); glVertex2i(left + width_ - 12, top + (*it)->height()); glVertex2i(left, top + (*it)->height()); glEnd(); glEnable(GL_TEXTURE_2D); // Re-Enable Texturing } (*it)->draw(xoffset, yoffset); } }
void shadow_render_mesh(int mesh_idx) { int n,k,poly_count; float f_dist; double dx,dy,dz,d_alpha; float *vertex_ptr,*vl,*cl; d3vct ray_move; d3pnt *pt,*spt,*ept,*hpt; map_mesh_type *mesh; map_mesh_poly_type *poly; view_light_spot_type *lspot; // for now, leverage the model shadow // arrays and only allow meshes with a limited // number of vertexes mesh=&map.mesh.meshes[mesh_idx]; if (mesh->nvertex>=max_model_vertex) return; // find all polys the shadow ray hits poly_count=shadow_build_poly_set_mesh(mesh_idx); if (poly_count==0) return; // get light and draw distance lspot=shadow_get_light_spot(&mesh->box.mid,(mesh->box.max.y-mesh->box.min.y)); f_dist=(float)lspot->intensity; // get distance alpha factor d_alpha=(double)lspot->intensity; d_alpha=1.0/(d_alpha*d_alpha); // start stenciling // never write to the depth buffer during this operation glEnable(GL_STENCIL_TEST); glDisable(GL_ALPHA_TEST); glDepthMask(GL_FALSE); // setup blending glColor4f(0.0f,0.0f,0.0f,1.0f); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // run through all the stenciled polygons // and ray trace against their planes // to create the shadow polygons for (k=0;k!=poly_count;k++) { // stencil the poly we are going // to draw a shadow on shadow_stencil_mesh_poly(shadow_poly_ptrs[k].mesh_idx,shadow_poly_ptrs[k].poly_idx); // run through all the vertexes of this mesh spt=shadow_spt; ept=shadow_ept; pt=mesh->vertexes; for (n=0;n!=mesh->nvertex;n++) { spt->x=pt->x; spt->y=pt->y; spt->z=pt->z; vector_create(&ray_move,lspot->pnt.x,lspot->pnt.y,lspot->pnt.z,spt->x,spt->y,spt->z); ept->x=spt->x-(int)(ray_move.x*f_dist); ept->y=spt->y-(int)(ray_move.y*f_dist); ept->z=spt->z-(int)(ray_move.z*f_dist); spt++; ept++; pt++; } ray_trace_mesh_poly_plane(mesh->nvertex,shadow_spt,shadow_ept,shadow_hpt,shadow_hits,shadow_poly_ptrs[k].mesh_idx,shadow_poly_ptrs[k].poly_idx); // setup the vertex objects vertex_ptr=view_bind_map_next_vertex_object(mesh->nvertex*(3+4)); if (vertex_ptr==NULL) { glDisable(GL_STENCIL_TEST); glDepthMask(GL_TRUE); return; } vl=vertex_ptr; cl=vertex_ptr+(mesh->nvertex*3); // vertexes hpt=shadow_hpt; for (n=0;n!=mesh->nvertex;n++) { // vertex *vl++=(float)hpt->x; *vl++=(float)hpt->y; *vl++=(float)hpt->z; // color dx=(hpt->x-lspot->pnt.x); dy=(hpt->y-lspot->pnt.y); dz=(hpt->z-lspot->pnt.z); hpt++; *cl++=0.0f; *cl++=0.0f; *cl++=0.0f; *cl++=1.0f-(float)(((dx*dx)+(dy*dy)+(dz*dz))*d_alpha); } view_unmap_current_vertex_object(); // shadows are blended and stenciled // we clear the stencil as we draw so // we can maintain the alpha levels glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); glStencilOp(GL_KEEP,GL_KEEP,GL_ZERO); glStencilFunc(GL_EQUAL,stencil_shadow,0xFF); // ray trace the polygon against // the plane of the polygon glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3,GL_FLOAT,0,0); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4,GL_FLOAT,0,(void*)((mesh->nvertex*3)*sizeof(float))); poly=mesh->polys; for (n=0;n!=mesh->npoly;n++) { glDrawRangeElements(GL_POLYGON,0,mesh->nvertex,poly->ptsz,GL_UNSIGNED_INT,(GLvoid*)poly->v); poly++; } glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); // unbind the vertex object view_unbind_current_vertex_object(); // erase the stencil shadow_stencil_clear_mesh_poly(); } // restore depth buffer and turn // off stenciling glDepthMask(GL_TRUE); glDisable(GL_STENCIL_TEST); }
void GL::stencilOp(Enum fail, Enum zfail, Enum zpass) { glStencilOp(fail, zfail, zpass); CHECK_GL_ERROR3(glStencilOp, fail, zfail, zpass); }
void LLDrawPoolWater::render(S32 pass) { LLFastTimer ftm(LLFastTimer::FTM_RENDER_WATER); if (mDrawFace.empty() || LLDrawable::getCurrentFrame() <= 1) { return; } //do a quick 'n dirty depth sort for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { LLFace* facep = *iter; facep->mDistance = -facep->mCenterLocal.mV[2]; } std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater()); LLGLEnable blend(GL_BLEND); if ((mVertexShaderLevel > 0) && !sSkipScreenCopy) { shade(); return; } LLVOSky *voskyp = gSky.mVOSkyp; stop_glerror(); if (!gGLManager.mHasMultitexture) { // Ack! No multitexture! Bail! return; } LLFace* refl_face = voskyp->getReflFace(); gPipeline.disableLights(); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); LLGLDisable cullFace(GL_CULL_FACE); // Set up second pass first mWaterImagep->addTextureStats(1024.f*1024.f); mWaterImagep->bind(1); gGL.getTexUnit(1)->activate(); glEnable(GL_TEXTURE_2D); // Texture unit 1 LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis(); F32 up_dot = camera_up * LLVector3::z_axis; LLColor4 water_color; if (LLViewerCamera::getInstance()->cameraUnderWater()) { water_color.setVec(1.f, 1.f, 1.f, 0.4f); } else { water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot)); } glColor4fv(water_color.mV); // Automatically generate texture coords for detail map glEnable(GL_TEXTURE_GEN_S); //texture unit 1 glEnable(GL_TEXTURE_GEN_T); //texture unit 1 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // Slowly move over time. F32 offset = fmod(gFrameTimeSeconds*2.f, 100.f); F32 tp0[4] = {16.f/256.f, 0.0f, 0.0f, offset*0.01f}; F32 tp1[4] = {0.0f, 16.f/256.f, 0.0f, offset*0.01f}; glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1); gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_ALPHA); gGL.getTexUnit(0)->activate(); glClearStencil(1); glClear(GL_STENCIL_BUFFER_BIT); LLGLEnable gls_stencil(GL_STENCIL_TEST); glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF); for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { LLFace *face = *iter; if (voskyp->isReflFace(face)) { continue; } face->bindTexture(); face->renderIndexed(); } // Now, disable texture coord generation on texture state 1 gGL.getTexUnit(1)->activate(); glDisable(GL_TEXTURE_2D); // Texture unit 1 glDisable(GL_TEXTURE_GEN_S); //texture unit 1 glDisable(GL_TEXTURE_GEN_T); //texture unit 1 LLImageGL::unbindTexture(1, GL_TEXTURE_2D); // Disable texture coordinate and color arrays gGL.getTexUnit(0)->activate(); LLImageGL::unbindTexture(0, GL_TEXTURE_2D); stop_glerror(); if (gSky.mVOSkyp->getCubeMap()) { gSky.mVOSkyp->getCubeMap()->enable(0); gSky.mVOSkyp->getCubeMap()->bind(); glMatrixMode(GL_TEXTURE); glLoadIdentity(); LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview(); LLMatrix4 camera_rot(camera_mat.getMat3()); camera_rot.invert(); glLoadMatrixf((F32 *)camera_rot.mMatrix); glMatrixMode(GL_MODELVIEW); LLOverrideFaceColor overrid(this, 1.f, 1.f, 1.f, 0.5f*up_dot); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { LLFace *face = *iter; if (voskyp->isReflFace(face)) { //refl_face = face; continue; } if (face->getGeomCount() > 0) { face->renderIndexed(); } } gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); if (gSky.mVOSkyp->getCubeMap()) { gSky.mVOSkyp->getCubeMap()->disable(); } LLImageGL::unbindTexture(0, GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); } glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); if (refl_face) { glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF); renderReflection(refl_face); } gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); }
void HouseKitchen::Render(Vec3& position, Vec2& dimension, Vec2& texture_coordinate, Vec2& texture_dimension, bool no_floor) { // (x, y, z), (w, h), (u, v), , (w, h) , , reflect , front, left, back, right, frontw, leftw, backw, rightw, up, down. Room::Render(position, dimension, texture_coordinate, texture_dimension, 3, no_floor, true, true, false, false, false, false, false, false, false, false); // Draw the rest of the room here. // Inside of the room. glPushMatrix(); // Creating the stencil before we create the scene. glEnable(GL_STENCIL_TEST); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glStencilFunc(GL_ALWAYS, 1, 1); //// We aren't rendering to the frame, so always pass the stencil test. glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // Disable depth testing. glDisable(GL_DEPTH_TEST); // To the floor. glPushMatrix(); BindTexture(floor_dark_diamonds_, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR); glTranslatef(0.0f, 0.125f, -dimension.getX()); glRotatef(90.0f, 1.0f, 0.0f, 0.0f); DrawPlane(position, dimension, texture_coordinate, texture_dimension, Vec3(0.0f, 1.0f, 0.0f), 3); // Back to the kitchen. glPopMatrix(); glEnable(GL_DEPTH_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // Turn on rendering to the frame buffer. glStencilFunc(GL_EQUAL, 1, 1); // Don't change the stencil values. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // To the reflected worktop. glPushMatrix(); // Making the kitchen objects upside down. glScalef(1.0f, -1.0f, 1.0f); // Placing the worktop exactly where I want it. glTranslatef((dimension.getX() / 2.0f) - 0.5f, 0.0f, -12.45f); glScalef(1.25f, 1.75f, 1.0f); glRotatef(270.0f, 0.0f, 1.0f, 0.0f); CreateWorkTop(position, Vec2(1.0f, 1.0f), texture_coordinate, texture_dimension); glRotatef(-270.0f, 0.0f, 1.0f, 0.0f); glTranslatef(5.0f, 0.0f, 3.75f); glScalef(1.25f, 1.0f, 1.0f); glRotatef(180.0f, 0.0f, 1.0f, 0.0f); CreateWorkTop(position, Vec2(1.0f, 1.0f), texture_coordinate, texture_dimension); // Back to the reflected kitchen. glPopMatrix(); // To the reflected teapot model. glPushMatrix(); glScalef(1.0f, -1.0f, 1.0f); glTranslatef((dimension.getX() / 2.0f) + 1.0f, 3.125f, (dimension.getX() / 2.0f) - 18.0f); glScalef(0.03125f, 0.03125f, 0.03125f); teapot_.Render(); // Back to the reflected kitchen. glPopMatrix(); // To the reflected cupboards. glPushMatrix(); glScalef(1.0f, -1.0f, 1.0f); glTranslatef((dimension.getX() / 2.0f), 5.0f, -12.45f); glScalef(1.0f, 1.25f, 1.0f); glRotatef(270.0f, 0.0f, 1.0f, 0.0f); CreateCupboard(position, Vec2(1.0f, 1.0f), texture_coordinate, texture_dimension); glTranslatef(0.0f, 0.0f, -3.0f); CreateCupboard(position, Vec2(1.0f, 1.0f), texture_coordinate, texture_dimension); glRotatef(-270.0f, 0.0f, 1.0f, 0.0f); glTranslatef(3.0f, 0.0f, 1.0f); glScalef(1.5f, 1.0f, 1.0f); glRotatef(180.0f, 0.0f, 1.0f, 0.0f); CreateCupboard(position, Vec2(1.0f, 1.0f), texture_coordinate, texture_dimension); glTranslatef(0.0f, 0.0f, -3.0f); CreateCupboard(position, Vec2(1.0f, 1.0f), texture_coordinate, texture_dimension); // Back to the kitchen. glPopMatrix(); // No longer need the stencil test. glDisable(GL_STENCIL_TEST); // To combine the flow and rendered reflection of the object. glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Lighting not really needed. glDisable(GL_LIGHTING); // To the floor. glPushMatrix(); BindTexture(floor_dark_diamonds_, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR); glTranslatef(0.0f, 0.125f, -dimension.getX()); glRotatef(90.0f, 1.0f, 0.0f, 0.0f); DrawPlane(position, dimension, texture_coordinate, texture_dimension, Vec3(0.0f, 1.0f, 0.0f), 3); // Back to the kitchen. glPopMatrix(); glEnable(GL_LIGHTING); //glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); // To the light shade. glPushMatrix(); // Places in a light shade. CreateLightShade(Vec3((dimension.getX() / 2.0f), -dimension.getY(), (-dimension.getX() / 2.0f)), Vec2(1.0f, 1.0f), texture_coordinate, texture_dimension); // Back to the kitchen. glPopMatrix(); // To the worktop. glPushMatrix(); glTranslatef((dimension.getX() / 2.0f) - 0.5f, 0.0f, -12.45f); glScalef(1.25f, 1.75f, 1.0f); glRotatef(270.0f, 0.0f, 1.0f, 0.0f); CreateWorkTop(position, Vec2(1.0f, 1.0f), texture_coordinate, texture_dimension); glRotatef(-270.0f, 0.0f, 1.0f, 0.0f); glTranslatef(5.0f, 0.0f, 3.75f); glScalef(1.25f, 1.0f, 1.0f); glRotatef(180.0f, 0.0f, 1.0f, 0.0f); CreateWorkTop(position, Vec2(1.0f, 1.0f), texture_coordinate, texture_dimension); // Back to the kitchen. glPopMatrix(); // To the teapot model. glPushMatrix(); glTranslatef((dimension.getX() / 2.0f) + 1.0f, 3.125f, (dimension.getX() / 2.0f) - 18.0f); glScalef(0.03125f, 0.03125f, 0.03125f); teapot_.Render(); // Back to the kitchen. glPopMatrix(); // To the cupboards. glPushMatrix(); glTranslatef((dimension.getX() / 2.0f), 5.0f, -12.45f); glScalef(1.0f, 1.25f, 1.0f); glRotatef(270.0f, 0.0f, 1.0f, 0.0f); CreateCupboard(position, Vec2(1.0f, 1.0f), texture_coordinate, texture_dimension); glTranslatef(0.0f, 0.0f, -3.0f); CreateCupboard(position, Vec2(1.0f, 1.0f), texture_coordinate, texture_dimension); glRotatef(-270.0f, 0.0f, 1.0f, 0.0f); glTranslatef(3.0f, 0.0f, 1.0f); glScalef(1.5f, 1.0f, 1.0f); glRotatef(180.0f, 0.0f, 1.0f, 0.0f); CreateCupboard(position, Vec2(1.0f, 1.0f), texture_coordinate, texture_dimension); glTranslatef(0.0f, 0.0f, -3.0f); CreateCupboard(position, Vec2(1.0f, 1.0f), texture_coordinate, texture_dimension); // Back to the kitchen. glPopMatrix(); // Back to the original 3D scene. glPopMatrix(); }
void MapCodegenState::begin_graph(graph_t* pGraph, box , point ) { // draw map double llx = pGraph->u.bb.LL.x; double lly = pGraph->u.bb.LL.y; double urx = pGraph->u.bb.UR.x; double ury = pGraph->u.bb.UR.y; double scaleX = (urx-llx); double scaleY = (ury-lly); //if(scaleY<scaleX) mapScale = (1.0/scaleX)*2.0; //else mapScale = (1.0/scaleY)*2.0; //mapScale *= 0.3; if(scaleY<scaleX) { mapScale = ( mapDestSize /scaleY); if(( scaleX * mapScale )> (orthoX*2.0-mapOffset*2.0) ) { mapScale = ( (orthoX*2.0-mapOffset*2.0)/scaleX); } } else { mapScale = ( mapDestSize /scaleX); if(( scaleY * mapScale )> (orthoX*2.0-mapOffset*2.0) ) { mapScale = ((orthoX*2.0-mapOffset*2.0)/scaleY); } } //gMousePosY = gViewSizeY-gMousePosY; short sw = (short)( (MSX(bbur.x) - MSX(bbll.x))/(2.0*orthoX) * gViewSizeX ); short sh = (short)( (MSY(bbur.y) - MSY(bbll.y))/(2.0*orthoY) * gViewSizeY ); short ssx = (short)( (MSX(bbll.x))/(2.0*orthoX) * gViewSizeX + (gViewSizeX/2) ); short ssy = (short)( (MSY(bbll.y))/(2.0*orthoY) * gViewSizeY + (gViewSizeY/2) ); short sex = (short)( ssx + sw ); short sey = (short)( ssy + sh ); if( (gMousePosX>=ssx) && (gMousePosX<=sex) && ((gViewSizeY-gMousePosY)>=ssy) && ((gViewSizeY-gMousePosY)<=sey) ) { gMouseIn = true; //gFade = 1.0; //cout << " in " ; // debug } else { gMouseIn = false; } if(!gMouseIn) { glColor4f( 0,0, 0.25 , 0.75*gFade); //glColor4f( 0.0,0.0,0.0, 0.5*gFade); } else { //glColor4f( 0.25,0.25, 0.5 , 0.75*gFade); glColor4f( 0,0, 0.35 , 0.75*gFade); //glColor4f( 0.0,0.0,0.0, 0.5*gFade); } //glBegin(GL_QUADS); box bound; bound = pGraph->u.bb; //glVertex3f( MSX(bbll.x),MSY(bbll.y), zpos ); //glVertex3f( MSX(bbur.x),MSY(bbll.y), zpos ); //glVertex3f( MSX(bbur.x),MSY(bbur.y), zpos ); //glVertex3f( MSX(bbll.x),MSY(bbur.y), zpos ); //glEnd(); //cout << " GL map start " << mapScale << endl; // setup stencil buffer display glEnable( GL_STENCIL_TEST ); glStencilFunc( GL_ALWAYS, 0x01, 0x01 ); glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE ); glBegin(GL_QUADS); glVertex3f( MSX(bbll.x),MSY(bbll.y), zpos ); glVertex3f( MSX(bbur.x),MSY(bbll.y), zpos ); glVertex3f( MSX(bbur.x),MSY(bbur.y), zpos ); glVertex3f( MSX(bbll.x),MSY(bbur.y), zpos ); glEnd(); glStencilFunc( GL_EQUAL, 0x01, 0x01 ); glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); // draw the rest glLineWidth(1.0); if(!gMouseIn) { glColor4f( 0.0,0.0,0.0, 0.5*gFade); } else { glColor4f( 0.0,0.0,1.0, 0.5*gFade); } glBegin(GL_LINES); glVertex3f( MSX(bbll.x),MSY(bbll.y), zpos ); glVertex3f( MSX(bbur.x),MSY(bbll.y), zpos ); glVertex3f( MSX(bbur.x),MSY(bbur.y), zpos ); glVertex3f( MSX(bbll.x),MSY(bbur.y), zpos ); glVertex3f( MSX(bbll.x),MSY(bbur.y), zpos ); glEnd(); }
/* ==================== RE_BeginFrame ==================== */ void RE_BeginFrame() { drawBufferCommand_t* cmd; if (!tr.registered) { return; } GLimp_LogComment("--- RE_BeginFrame ---\n"); tr.frameCount++; tr.frameSceneNum = 0; tr.viewCount = 0; // do overdraw measurement if (r_measureOverdraw->integer) { if (glConfig.stencilBits < 4) { ri.Printf(PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits); ri.Cvar_Set("r_measureOverdraw", "0"); r_measureOverdraw->modified = false; } else { R_SyncRenderThread(); glEnable(GL_STENCIL_TEST); glStencilMask(~0U); GL_ClearStencil(0U); glStencilFunc(GL_ALWAYS, 0U, ~0U); glStencilOp(GL_KEEP, GL_INCR, GL_INCR); } r_measureOverdraw->modified = false; } else { // this is only reached if it was on and is now off if (r_measureOverdraw->modified) { R_SyncRenderThread(); glDisable(GL_STENCIL_TEST); } r_measureOverdraw->modified = false; } // texturemode stuff if (r_textureMode->modified) { R_SyncRenderThread(); GL_TextureMode(r_textureMode->string); r_textureMode->modified = false; } // check for errors if (!r_ignoreGLErrors->integer) { int err; char s[128]; R_SyncRenderThread(); if ((err = glGetError()) != GL_NO_ERROR) { switch (err) { case GL_INVALID_ENUM: strcpy(s, "GL_INVALID_ENUM"); break; case GL_INVALID_VALUE: strcpy(s, "GL_INVALID_VALUE"); break; case GL_INVALID_OPERATION: strcpy(s, "GL_INVALID_OPERATION"); break; case GL_STACK_OVERFLOW: strcpy(s, "GL_STACK_OVERFLOW"); break; case GL_STACK_UNDERFLOW: strcpy(s, "GL_STACK_UNDERFLOW"); break; case GL_OUT_OF_MEMORY: strcpy(s, "GL_OUT_OF_MEMORY"); break; case GL_TABLE_TOO_LARGE: strcpy(s, "GL_TABLE_TOO_LARGE"); break; case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: strcpy(s, "GL_INVALID_FRAMEBUFFER_OPERATION_EXT"); break; default: Com_sprintf(s, sizeof(s), "0x%X", err); break; } // ri.Error(ERR_FATAL, "caught OpenGL error: %s in file %s line %i", s, // filename, line); ri.Error(ERR_FATAL, "RE_BeginFrame() - glGetError() failed (%s)!", s); } } // draw buffer stuff cmd = (drawBufferCommand_t*) R_GetCommandBuffer(sizeof(*cmd)); if (!cmd) { return; } cmd->commandId = RC_DRAW_BUFFER; if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT")) { cmd->buffer = (int) GL_FRONT; } else { cmd->buffer = (int) GL_BACK; } }
void set_gl_options (TRenderMode mode) { currentMode = mode; switch (mode) { case GUI: glEnable (GL_TEXTURE_2D); glDisable (GL_DEPTH_TEST); glDisable (GL_CULL_FACE); glDisable (GL_LIGHTING); glDisable (GL_NORMALIZE); glDisable (GL_ALPHA_TEST); glEnable (GL_BLEND); glDisable (GL_STENCIL_TEST); glDisable (GL_TEXTURE_GEN_S); glDisable (GL_TEXTURE_GEN_T); glDisable (GL_COLOR_MATERIAL); glDepthMask (GL_TRUE); glShadeModel (GL_SMOOTH); glDepthFunc (GL_LESS); glDisable (GL_FOG); break; case GAUGE_BARS: glEnable (GL_TEXTURE_2D); glDisable (GL_DEPTH_TEST); glDisable (GL_CULL_FACE); glDisable (GL_LIGHTING); glDisable (GL_NORMALIZE); glDisable (GL_ALPHA_TEST); glEnable (GL_BLEND); glDisable (GL_STENCIL_TEST); glEnable (GL_TEXTURE_GEN_S); glEnable (GL_TEXTURE_GEN_T); glDisable (GL_COLOR_MATERIAL); glDepthMask (GL_TRUE); glShadeModel (GL_SMOOTH); glDepthFunc (GL_LESS); glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); break; case TEXFONT: glEnable (GL_TEXTURE_2D); glDisable (GL_DEPTH_TEST); glDisable (GL_CULL_FACE); glDisable (GL_LIGHTING); glDisable (GL_NORMALIZE); glDisable (GL_ALPHA_TEST); glEnable (GL_BLEND); glDisable (GL_STENCIL_TEST); glDisable (GL_TEXTURE_GEN_S); glDisable (GL_TEXTURE_GEN_T); glDisable (GL_COLOR_MATERIAL); glDepthMask (GL_TRUE); glShadeModel (GL_SMOOTH); glDepthFunc (GL_LESS); break; case COURSE: glEnable (GL_TEXTURE_2D); glEnable (GL_DEPTH_TEST); glEnable (GL_CULL_FACE); glEnable (GL_LIGHTING); glDisable (GL_NORMALIZE); glDisable (GL_ALPHA_TEST); glEnable (GL_BLEND); glDisable (GL_STENCIL_TEST); glEnable (GL_TEXTURE_GEN_S); glEnable (GL_TEXTURE_GEN_T); glEnable (GL_COLOR_MATERIAL); glDepthMask (GL_TRUE); glShadeModel (GL_SMOOTH); glDepthFunc (GL_LEQUAL); glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); break; case TREES: glEnable (GL_TEXTURE_2D); glEnable (GL_DEPTH_TEST); glDisable (GL_CULL_FACE); glEnable (GL_LIGHTING); glDisable (GL_NORMALIZE); glEnable (GL_ALPHA_TEST); glEnable (GL_BLEND); glDisable (GL_STENCIL_TEST); glDisable (GL_TEXTURE_GEN_S); glDisable (GL_TEXTURE_GEN_T); glDisable (GL_COLOR_MATERIAL); glDepthMask (GL_TRUE); glShadeModel (GL_SMOOTH); glDepthFunc (GL_LESS); glAlphaFunc (GL_GEQUAL, 0.5); break; case PARTICLES: glEnable (GL_TEXTURE_2D); glEnable (GL_DEPTH_TEST); glDisable (GL_CULL_FACE); glDisable (GL_LIGHTING); glDisable (GL_NORMALIZE); glEnable (GL_ALPHA_TEST); glEnable (GL_BLEND); glDisable (GL_STENCIL_TEST); glDisable (GL_TEXTURE_GEN_S); glDisable (GL_TEXTURE_GEN_T); glDisable (GL_COLOR_MATERIAL); glDepthMask (GL_TRUE); glShadeModel (GL_SMOOTH); glDepthFunc (GL_LESS); glAlphaFunc (GL_GEQUAL, 0.5); break; case SKY: glEnable (GL_TEXTURE_2D); glDisable (GL_DEPTH_TEST); glDisable (GL_CULL_FACE); glDisable (GL_LIGHTING); glDisable (GL_NORMALIZE); glDisable (GL_ALPHA_TEST); glEnable (GL_BLEND); glDisable (GL_STENCIL_TEST); glDisable (GL_TEXTURE_GEN_S); glDisable (GL_TEXTURE_GEN_T); glDisable (GL_COLOR_MATERIAL); glDepthMask (GL_FALSE); glShadeModel (GL_SMOOTH); glDepthFunc (GL_LESS); break; case FOG_PLANE: glDisable (GL_TEXTURE_2D); glEnable (GL_DEPTH_TEST); glDisable (GL_CULL_FACE); glDisable (GL_LIGHTING); glDisable (GL_NORMALIZE); glDisable (GL_ALPHA_TEST); glEnable (GL_BLEND); glDisable (GL_STENCIL_TEST); glDisable (GL_TEXTURE_GEN_S); glDisable (GL_TEXTURE_GEN_T); glDisable (GL_COLOR_MATERIAL); glDepthMask (GL_TRUE); glShadeModel (GL_SMOOTH); glDepthFunc (GL_LESS); break; case TUX: glDisable (GL_TEXTURE_2D); glEnable (GL_DEPTH_TEST); glEnable (GL_CULL_FACE); glEnable (GL_LIGHTING); glEnable (GL_NORMALIZE); glDisable (GL_ALPHA_TEST); glEnable (GL_BLEND); glDisable (GL_STENCIL_TEST); glDisable (GL_TEXTURE_GEN_S); glDisable (GL_TEXTURE_GEN_T); glDisable (GL_COLOR_MATERIAL); glDepthMask (GL_TRUE); glShadeModel (GL_SMOOTH); glDepthFunc (GL_LESS); break; case TUX_SHADOW: glDisable (GL_TEXTURE_2D); glEnable (GL_DEPTH_TEST); glDisable (GL_LIGHTING); glDisable (GL_NORMALIZE); glDisable (GL_ALPHA_TEST); glEnable (GL_BLEND); glDisable (GL_COLOR_MATERIAL); glShadeModel (GL_SMOOTH); glDepthFunc (GL_LESS); #ifdef USE_STENCIL_BUFFER glDisable (GL_CULL_FACE); glEnable (GL_STENCIL_TEST); glDepthMask (GL_FALSE); glStencilFunc (GL_EQUAL, 0, ~0); glStencilOp (GL_KEEP, GL_KEEP, GL_INCR); #else glEnable (GL_CULL_FACE); glDisable (GL_STENCIL_TEST); glDepthMask (GL_TRUE); #endif break; case TRACK_MARKS: glEnable (GL_TEXTURE_2D); glEnable (GL_DEPTH_TEST); glDisable (GL_CULL_FACE); glEnable (GL_LIGHTING); glDisable (GL_NORMALIZE); glDisable (GL_ALPHA_TEST); glEnable (GL_BLEND); glDisable (GL_STENCIL_TEST); glDisable (GL_COLOR_MATERIAL); glDisable (GL_TEXTURE_GEN_S); glDisable (GL_TEXTURE_GEN_T); glDepthMask (GL_FALSE); glShadeModel (GL_SMOOTH); glDepthFunc (GL_LEQUAL); break; default: Message ("not a valid render mode", ""); } }
// The MAIN function, from here we start our application and run our Game loop int main() { // Init GLFW glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "Some OpenGL Testing", nullptr, nullptr); // Windowed glfwMakeContextCurrent(window); // Set the required callback functions glfwSetKeyCallback(window, key_callback); glfwSetCursorPosCallback(window, mouse_callback); glfwSetScrollCallback(window, scroll_callback); glfwSetMouseButtonCallback(window, mouse_button_click_callback); // Options glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); // Initialize GLEW to setup the OpenGL Function pointers glewExperimental = GL_TRUE; glewInit(); // Define the viewport dimensions glViewport(0, 0, screenWidth, screenHeight); // Setup some OpenGL options glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); glDepthFunc(GL_LESS); // Set to always pass the depth test (same effect as glDisable(GL_DEPTH_TEST)) glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // Setup and compile our shaders Shader shader("shaders/advanced.vs", "shaders/advanced.frag"); Shader stencil("shaders/stencil.vs", "shaders/stencil.frag"); #pragma region "object_initialization" // Set the object data (buffers, vertex attributes) GLfloat cubeVertices[] = { // Positions // Texture Coords -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; GLfloat planeVertices[] = { // Positions 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, 5.0f, 0.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, 5.0f, -0.5f, -5.0f, 2.0f, 2.0f }; // Setup cube VAO GLuint cubeVAO, cubeVBO; glGenVertexArrays(1, &cubeVAO); glGenBuffers(1, &cubeVBO); glBindVertexArray(cubeVAO); glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glBindVertexArray(0); // Setup plane VAO GLuint planeVAO, planeVBO; glGenVertexArrays(1, &planeVAO); glGenBuffers(1, &planeVBO); glBindVertexArray(planeVAO); glBindBuffer(GL_ARRAY_BUFFER, planeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glBindVertexArray(0); // Load textures GLuint cubeTexture = loadTexture("media/container.jpg"); GLuint floorTexture = loadTexture("media/awesomeface.png"); #pragma endregion // Game loop while (!glfwWindowShouldClose(window)) { GLfloat currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; // Check and call events glfwPollEvents(); handle_input(window); // Clear the colorbuffer glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Set uniforms stencil.use(); glm::mat4 model; glm::mat4 view = camera.get_view_matrix(); glm::mat4 projection = glm::perspective(camera.m_zoom, (float)screenWidth / (float)screenHeight, 0.1f, 100.0f); glUniformMatrix4fv(glGetUniformLocation(stencil.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(glGetUniformLocation(stencil.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); shader.use(); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); // Draw floor as normal, we only care about the containers. The floor should NOT fill the stencil buffer so we set its mask to 0x00 glStencilMask(0x00); // Floor glBindVertexArray(planeVAO); glBindTexture(GL_TEXTURE_2D, floorTexture); model = glm::mat4(); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); // == ============= // 1st. Render pass, draw objects as normal, filling the stencil buffer glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilMask(0xFF); // Cubes glBindVertexArray(cubeVAO); glBindTexture(GL_TEXTURE_2D, cubeTexture); model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); glDrawArrays(GL_TRIANGLES, 0, 36); model = glm::mat4(); model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f)); glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); // == ============= // 2nd. Render pass, now draw slightly scaled versions of the objects, this time disabling stencil writing. // Because stencil buffer is now filled with several 1s. The parts of the buffer that are 1 are now not drawn, thus only drawing // the objects' size differences, making it look like borders. glStencilFunc(GL_NOTEQUAL, 1, 0xFF); glStencilMask(0x00); glDisable(GL_DEPTH_TEST); stencil.use(); GLfloat scale = 1.1; // Cubes glBindVertexArray(cubeVAO); glBindTexture(GL_TEXTURE_2D, cubeTexture); model = glm::mat4(); model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f)); model = glm::scale(model, glm::vec3(scale, scale, scale)); glUniformMatrix4fv(glGetUniformLocation(stencil.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); glDrawArrays(GL_TRIANGLES, 0, 36); model = glm::mat4(); model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f)); model = glm::scale(model, glm::vec3(scale, scale, scale)); glUniformMatrix4fv(glGetUniformLocation(stencil.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); glStencilMask(0xFF); glEnable(GL_DEPTH_TEST); // Swap the buffers glfwSwapBuffers(window); } glfwTerminate(); return 0; }
void PlanePixelNode::onDraw(const cocos2d::Mat4 &transform, uint32_t flags) { auto glProgram = _programState->getGLProgram(); glProgram->use(); auto loc = glProgram->getUniformLocation("u_move_line"); glProgram->setUniformLocationWith1f(loc, _moveLine); loc = glProgram->getUniformLocation("u_move_width"); glProgram->setUniformLocationWith1f(loc, _moveWidth); loc = glProgram->getUniformLocation("u_x_diff"); glProgram->setUniformLocationWith1f(loc, _baseXDiff_current + _varyXDiff* (getOpacity()/255.f-0.5f)); glProgram->setUniformsForBuiltins(transform); glBindBuffer(GL_ARRAY_BUFFER, _vbo); if (Configuration::getInstance()->supportsShareableVAO()) { GL::bindVAO(_vao); } else { // TODO } // glEnable (GL_BLEND); // glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); glEnable(GL_CULL_FACE); // shadow cover打开depth test同时在fsh中对a为0的进行discard,以保证重合交叠处不会交叠而加深。 glEnable(GL_DEPTH_TEST); glDepthMask(true); if (_stencil) { glEnable(GL_STENCIL_TEST); // Draw floor glStencilFunc(GL_ALWAYS, 1, 0xFF); // Set any stencil to 1 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilMask(0xFF); // Write to stencil buffer glDepthMask(GL_FALSE); // Don't write to depth buffer glClear(GL_STENCIL_BUFFER_BIT); // Clear stencil buffer (0 by default) } if (_stenciled) { glEnable(GL_STENCIL_TEST); glStencilFunc(GL_EQUAL, 1, 0xFF); // Pass test if stencil value is 1 glStencilMask(0x00); // Don't write anything to stencil buffer glDepthMask(GL_TRUE); // Write to depth buffer } glDrawArrays(GL_TRIANGLES, 0, _count); if (Configuration::getInstance()->supportsShareableVAO()) { GL::bindVAO(0); } glDisable(GL_STENCIL_TEST); glBindBuffer(GL_ARRAY_BUFFER, 0); glDisable(GL_DEPTH_TEST); glDepthMask(false); glEnable (GL_BLEND); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_count); CHECK_GL_ERROR_DEBUG(); }
int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, nullptr, nullptr); glfwMakeContextCurrent(window); updateTitle(); glewExperimental = GL_TRUE; glewInit(); glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); glewExperimental = GL_TRUE; glewInit(); glEnable(GL_DEPTH_TEST); GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); GLuint vbo; glGenBuffers(1, &vbo); GLfloat vertices[] = { // Positions // TexCoords -1.0f, -1.0f, -0.5f, 0.0f, 0.0f, 1.0f, -1.0f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, -0.5f, 1.0f, 1.0f, -1.0f, 1.0f, -0.5f, 0.0f, 1.0f, -1.0f, -1.0f, -0.5f, 0.0f, 0.0f }; glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); GLuint program = createProgram(); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); GLuint texture = loadTexture("../textures/container.jpg"); GLuint texture2 = loadTexture("../textures/model.png"); GLint modelUniform = glGetUniformLocation(program, "model"); GLint colorUniform = glGetUniformLocation(program, "color"); glm::mat4 view = glm::lookAt( glm::vec3(9.0f, -0.5f, 2.5f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f) ); glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 0.01f, 100.0f); glUniformMatrix4fv(glGetUniformLocation(program, "viewProj"), 1, GL_FALSE, glm::value_ptr(projection * view)); Mesh m("../models/monkeyhead.obj"); glfwSetKeyCallback(window, key_callback); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glUniform1i(glGetUniformLocation(program, "tex"), 0); std::cout << "Stencil code ON: S " << std::endl; std::cout << "Stencil code OFF: A " << std::endl; while (!glfwWindowShouldClose(window)) { GLfloat currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; glfwPollEvents(); do_movement(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); float time = glfwGetTime(); glm::mat4 model; glm::mat4 modelScale; modelScale = glm::rotate( model, time * glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f) ); modelScale = glm::scale(modelScale, glm::vec3(1.3f)); modelScale = glm::translate(modelScale, glm::vec3(0.0, 0.0, 2.0)); glUniformMatrix4fv(modelUniform, 1, GL_FALSE, glm::value_ptr(modelScale)); // Draw model glBindVertexArray(vao); glBindTexture(GL_TEXTURE_2D, texture); glUniform3f(colorUniform, 1.0f, 1.0f, 1.0f); m.render(); // Draw floor if (stencil) { glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 0xffffff); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilMask(0xffffff); glDepthMask(GL_FALSE); glClear(GL_STENCIL_BUFFER_BIT); } glBindVertexArray(vao); glm::mat4 model2 = glm::translate(model, glm::vec3(2.0f * cos(glfwGetTime()), 2.0f * sin(glfwGetTime()), 0.0)); model2 = glm::scale( model2, glm::vec3(4.5f) ); glUniform3f(colorUniform, 0.75f, 0.0f, 0.0f); glUniformMatrix4fv(modelUniform, 1, GL_FALSE, glm::value_ptr(model2)); glBindTexture(GL_TEXTURE_2D, texture2); glDrawArrays(GL_TRIANGLES, 0, 6); // Draw model reflection if (stencil) { glStencilFunc(GL_EQUAL, 1, 0xffffff); // Only draw model if stencil value has equal glStencilMask(0x000000); glDepthMask(GL_TRUE); } modelScale = glm::translate(modelScale, glm::vec3(0.0, 0.0, -3.0)); modelScale = glm::translate(modelScale, glm::vec3(0.0, 0.0, -1.0)); modelScale = glm::scale( modelScale, glm::vec3(1, 1, -1) ); glUniformMatrix4fv(modelUniform, 1, GL_FALSE, glm::value_ptr(modelScale)); glUniform3f(colorUniform, 0.25f, 0.0f, 0.0f); glBindTexture(GL_TEXTURE_2D, texture); m.render(); if (stencil) { glDisable(GL_STENCIL_TEST); } // Swap buffers glfwSwapBuffers(window); } glDeleteTextures(1, &texture); glDeleteProgram(program); // TODO: Clear shaders p.e: glDeleteShader(vsCode); glDeleteBuffers(1, &vbo); glDeleteVertexArrays(1, &vao); return 0; };
static void nvpr_render_shape(void *render, LVGShapeCollection *shapecol, LVGColorTransform *cxform, float ratio, int blend_mode) { //render_ctx *ctx = render; for (int j = 0; j < shapecol->num_shapes; j++) { NSVGshape *shape = shapecol->shapes + j; NSVGshape *shape2 = shapecol->morph ? shapecol->morph->shapes + j : 0; GLuint pathObj = shape->cache; if (shape2) pathObj = morph_shape(shape, shape2, ratio); /*GLfloat object_bbox[4], fill_bbox[4], stroke_bbox[4]; glGetPathParameterfvNV(pathObj, GL_PATH_OBJECT_BOUNDING_BOX_NV, object_bbox); glGetPathParameterfvNV(pathObj, GL_PATH_FILL_BOUNDING_BOX_NV, fill_bbox); glGetPathParameterfvNV(pathObj, GL_PATH_STROKE_BOUNDING_BOX_NV, stroke_bbox);*/ glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); switch(blend_mode) { case BLEND_LAYER: assert(0); break; case BLEND_MULTIPLY: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); break; case BLEND_SCREEN: glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); break; case BLEND_LIGHTEN: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_MAX); break; case BLEND_DARKEN: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_MIN); break; case BLEND_DIFFERENCE: assert(0); break; case BLEND_ADD: glBlendFunc(GL_ONE, GL_ONE); break; case BLEND_SUBTRACT: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); break; case BLEND_INVERT: assert(0); break; case BLEND_ALPHA: assert(0); break; case BLEND_ERASE: assert(0); break; case BLEND_OVERLAY: assert(0); glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); break; case BLEND_HARDLIGHT: assert(0); break; } glStencilFunc(GL_NOTEQUAL, 0, 0x1F); glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); glEnable(GL_STENCIL_TEST); if (NSVG_PAINT_NONE != shape->fill.type) { if (NSVG_PAINT_COLOR == shape->fill.type) { NVGcolor c = transformColor(nvgColorU32(shape->fill.color), cxform); glColor4f(c.r, c.g, c.b, c.a); } else if (NSVG_PAINT_LINEAR_GRADIENT == shape->fill.type) LinearGrad(shape, cxform, 1); else if (NSVG_PAINT_RADIAL_GRADIENT == shape->fill.type) RadialGrad(shape, cxform, 1); else if (NSVG_PAINT_IMAGE == shape->fill.type) ImagePaint(shape, cxform, 1); glStencilFillPathNV(pathObj, (NSVG_FILLRULE_EVENODD == shape->fillRule) ? GL_INVERT : GL_COUNT_UP_NV, 0x1F); glCoverFillPathNV(pathObj, GL_BOUNDING_BOX_NV); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glPathTexGenNV(GL_TEXTURE0, GL_NONE, 0, NULL); glPathColorGenNV(GL_PRIMARY_COLOR, GL_NONE, 0, NULL); glDisable(GL_TEXTURE_2D); } if (/*NSVG_PAINT_NONE != shape->stroke.type*/NSVG_PAINT_COLOR == shape->stroke.type) { if (NSVG_PAINT_COLOR == shape->stroke.type) { NVGcolor c = transformColor(nvgColorU32(shape->stroke.color), cxform); glColor4f(c.r, c.g, c.b, c.a); }/* else if (NSVG_PAINT_LINEAR_GRADIENT == shape->stroke.type) LinearGrad(shape, cxform, 0); else if (NSVG_PAINT_RADIAL_GRADIENT == shape->stroke.type) RadialGrad(shape, cxform, 0); else if (NSVG_PAINT_IMAGE == shape->stroke.type) ImagePaint(shape, cxform, 0);*/ glPathParameterfNV(pathObj, GL_PATH_STROKE_WIDTH_NV, shape->strokeWidth); if (NSVG_JOIN_ROUND == shape->strokeLineJoin) glPathParameteriNV(pathObj, GL_PATH_JOIN_STYLE_NV, GL_ROUND_NV); else if (NSVG_JOIN_BEVEL == shape->strokeLineJoin) glPathParameteriNV(pathObj, GL_PATH_JOIN_STYLE_NV, GL_BEVEL_NV); else if (NSVG_JOIN_MITER == shape->strokeLineJoin) glPathParameteriNV(pathObj, GL_PATH_JOIN_STYLE_NV, GL_MITER_TRUNCATE_NV); glPathParameterfNV(pathObj, GL_PATH_MITER_LIMIT_NV, shape->miterLimit); if (NSVG_CAP_ROUND == shape->strokeLineCap) glPathParameteriNV(pathObj, GL_PATH_END_CAPS_NV, GL_ROUND_NV); else if (NSVG_CAP_BUTT == shape->strokeLineCap) glPathParameteriNV(pathObj, GL_PATH_END_CAPS_NV, GL_FLAT); else if (NSVG_CAP_SQUARE == shape->strokeLineCap) glPathParameteriNV(pathObj, GL_PATH_END_CAPS_NV, GL_SQUARE_NV); GLint reference = 0x1; glStencilStrokePathNV(pathObj, reference, 0x1F); glCoverStrokePathNV(pathObj, GL_BOUNDING_BOX_NV); glPathColorGenNV(GL_PRIMARY_COLOR, GL_NONE, 0, NULL); } glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); if (shape2) glDeletePathsNV(pathObj, 1); } }
VG_API_CALL void vgDrawPath(VGPath path, VGbitfield paintModes) { SHPath *p; SHMatrix3x3 mi; SHfloat mgl[16]; SHPaint *fill, *stroke; SHRectangle *rect; VG_GETCONTEXT(VG_NO_RETVAL); VG_RETURN_ERR_IF(!shIsValidPath(context, path), VG_BAD_HANDLE_ERROR, VG_NO_RETVAL); VG_RETURN_ERR_IF(paintModes & (~(VG_STROKE_PATH | VG_FILL_PATH)), VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL); /* Check whether scissoring is enabled and scissor rectangle is valid */ if (context->scissoring == VG_TRUE) { rect = &context->scissor.items[0]; if (context->scissor.size == 0) VG_RETURN( VG_NO_RETVAL ); if (rect->w <= 0.0f || rect->h <= 0.0f) VG_RETURN( VG_NO_RETVAL ); glScissor( (GLint)rect->x, (GLint)rect->y, (GLint)rect->w, (GLint)rect->h ); glEnable( GL_SCISSOR_TEST ); } p = (SHPath*)path; /* If user-to-surface matrix invertible tessellate in surface space for better path resolution */ if (shIsTessCacheValid( context, p ) == VG_FALSE) { if (shInvertMatrix(&context->pathTransform, &mi)) { shFlattenPath(p, 1); shTransformVertices(&mi, p); }else shFlattenPath(p, 0); shFindBoundbox(p); } /* TODO: Turn antialiasing on/off */ glDisable(GL_LINE_SMOOTH); glDisable(GL_POLYGON_SMOOTH); glEnable(GL_MULTISAMPLE); /* Pick paint if available or default*/ fill = (context->fillPaint ? context->fillPaint : &context->defaultPaint); stroke = (context->strokePaint ? context->strokePaint : &context->defaultPaint); /* Apply transformation */ shMatrixToGL(&context->pathTransform, mgl); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glMultMatrixf(mgl); if (paintModes & VG_FILL_PATH) { /* Tesselate into stencil */ glEnable(GL_STENCIL_TEST); /* Clear the stencil buffer first */ glStencilFunc(GL_ALWAYS, 0, 0); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); shDrawBoundBox(context, p, VG_FILL_PATH); glStencilFunc(GL_ALWAYS, 0, 0); glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); shDrawVertices(p, GL_TRIANGLE_FAN); /* Setup blending */ updateBlendingStateGL(context, fill->type == VG_PAINT_TYPE_COLOR && fill->color.a == 1.0f); /* Draw paint where stencil odd */ glStencilFunc(GL_EQUAL, 1, 1); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); shDrawPaintMesh(context, &p->min, &p->max, VG_FILL_PATH, GL_TEXTURE0); /* Reset state */ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); } /* TODO: Turn antialiasing on/off */ glDisable(GL_LINE_SMOOTH); glDisable(GL_POLYGON_SMOOTH); glEnable(GL_MULTISAMPLE); if ((paintModes & VG_STROKE_PATH) && context->strokeLineWidth > 0.0f) { if (1) {/*context->strokeLineWidth > 1.0f) {*/ if (shIsStrokeCacheValid( context, p ) == VG_FALSE) { /* Generate stroke triangles in user space */ shVector2ArrayClear(&p->stroke); shStrokePath(context, p); } /* Stroke into stencil */ glEnable(GL_STENCIL_TEST); /* Clear the stencil buffer first */ glStencilFunc(GL_ALWAYS, 0, 0); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); shDrawBoundBox(context, p, VG_STROKE_PATH); glStencilFunc(GL_NOTEQUAL, 1, 1); glStencilOp(GL_KEEP, GL_INCR, GL_INCR); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); shDrawStroke(p); /* Setup blending */ updateBlendingStateGL(context, stroke->type == VG_PAINT_TYPE_COLOR && stroke->color.a == 1.0f); /* Draw paint where stencil odd */ glStencilFunc(GL_EQUAL, 1, 1); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); shDrawPaintMesh(context, &p->min, &p->max, VG_STROKE_PATH, GL_TEXTURE0); /* Reset state */ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); }else{ /* Simulate thin stroke by alpha */ SHColor c = stroke->color; if (context->strokeLineWidth < 1.0f) c.a *= context->strokeLineWidth; /* Draw contour as a line */ glDisable(GL_MULTISAMPLE); glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4fv((GLfloat*)&c); shDrawVertices(p, GL_LINE_STRIP); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); } } glDisable(GL_MULTISAMPLE); glPopMatrix(); if (context->scissoring == VG_TRUE) glDisable( GL_SCISSOR_TEST ); VG_RETURN(VG_NO_RETVAL); }
//------------------------------------------------------------------------------ void display() { glf::manager::timings->StartSection(glf::section::Frame); // Optimize far plane glm::mat4 projection = ctx::camera->Projection(); glm::mat4 view = ctx::camera->View(); float nearValue = ctx::camera->Near(); glm::vec3 viewPos = ctx::camera->Eye(); // Update lighting if needed glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); if(app->updateLighting) { app->skyBuilder.SetSunFactor(app->skyParams.sunFactor); app->skyBuilder.SetPosition(app->skyParams.sunTheta,app->skyParams.sunPhi); app->skyBuilder.SetTurbidity(float(app->skyParams.turbidity)); app->skyBuilder.Build(app->probeLight.cubeTex); app->probeBuilder.Filter(app->probeLight); float sunLuminosity = glm::max(glm::dot(app->skyBuilder.sunIntensity, glm::vec3(0.299f, 0.587f, 0.114f)), 0.0001f); glm::vec3 dir; dir.x = -sin(app->skyParams.sunTheta)*cos(app->skyParams.sunPhi); dir.y = -sin(app->skyParams.sunTheta)*sin(app->skyParams.sunPhi); dir.z = -cos(app->skyParams.sunTheta); app->csmLight.SetDirection(dir); app->csmLight.SetIntensity(glm::vec3(sunLuminosity)); app->updateLighting = false; } // Update terrain if needed if(app->updateTerrain) { for(unsigned int i=0;i<app->scene.terrainMeshes.size();++i) { app->scene.terrainMeshes[i].Tesselation(app->terrainParams.tileResolution, app->terrainParams.depthFactors[i], app->terrainParams.tessFactor, app->terrainParams.projFactor); app->terrainBuilder.BuildNormals( app->scene.terrainMeshes[i].heightTex, app->scene.terrainMeshes[i].normalTex, app->scene.terrainMeshes[i].terrainSize, app->terrainParams.depthFactors[i]); } app->updateTerrain = false; } // Enable writting into the depth buffer glDepthMask(true); glEnable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glf::manager::timings->StartSection(glf::section::CsmBuilder); app->csmBuilder.Draw( app->csmLight, *ctx::camera, app->csmParams.cascadeAlpha, app->csmParams.blendFactor, app->scene); glf::manager::timings->EndSection(glf::section::CsmBuilder); // Enable writting into the stencil buffer glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); if(ctx::drawWire) glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); glf::manager::timings->StartSection(glf::section::Gbuffer); app->gbuffer.Draw( projection, view, app->scene); glf::manager::timings->EndSection(glf::section::Gbuffer); if(ctx::drawWire) glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glDisable(GL_DEPTH_TEST); glDepthMask(false); // Disable writting into the stencil buffer // And activate stencil comparison glStencilFunc(GL_EQUAL, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); switch(app->activeBuffer) { case bufferType::GB_COMPOSITION : glBindFramebuffer(GL_FRAMEBUFFER,app->renderTarget1.framebuffer); glClear(GL_COLOR_BUFFER_BIT); // Render cube map glDisable(GL_STENCIL_TEST); glCullFace(GL_FRONT); app->cubeMap.Draw( projection, view, app->probeLight.cubeTex); glCullFace(GL_BACK); glEnable(GL_STENCIL_TEST); // Render sky lighting glf::manager::timings->StartSection(glf::section::SkyRender); app->probeRenderer.Draw(app->probeLight, app->gbuffer, viewPos, app->renderTarget1); glf::manager::timings->EndSection(glf::section::SkyRender); glBindFramebuffer(GL_FRAMEBUFFER,app->renderTarget2.framebuffer); glClear(GL_COLOR_BUFFER_BIT); // Render ssao::ssao pass glf::manager::timings->StartSection(glf::section::SsaoRender); app->ssao.Draw( app->gbuffer, view, nearValue, app->ssaoParams.beta, app->ssaoParams.epsilon, app->ssaoParams.kappa, app->ssaoParams.sigma, app->ssaoParams.radius, app->ssaoParams.nSamples, app->renderTarget2); glf::manager::timings->EndSection(glf::section::SsaoRender); glBindFramebuffer(GL_FRAMEBUFFER,app->renderTarget3.framebuffer); // Render ssao::bilateral pass1 glf::manager::timings->StartSection(glf::section::SsaoBlur); app->ssao.Draw( app->renderTarget2.texture, app->gbuffer.positionTex, view, app->ssaoParams.sigmaScreen, app->ssaoParams.sigmaDepth, app->ssaoParams.nTaps, glm::vec2(1,0), app->renderTarget3); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc( GL_ZERO, GL_SRC_ALPHA); // Do a multiplication between SSAO and sky lighting glBindFramebuffer(GL_FRAMEBUFFER,app->renderTarget1.framebuffer); // Render ssao::bilateral pass2 app->ssao.Draw( app->renderTarget3.texture, app->gbuffer.positionTex, view, app->ssaoParams.sigmaScreen, app->ssaoParams.sigmaDepth, app->ssaoParams.nTaps, glm::vec2(0,1), app->renderTarget1); glf::manager::timings->EndSection(glf::section::SsaoBlur); glBlendFunc( GL_ONE, GL_ONE); // Render csm/sun light pass glf::manager::timings->StartSection(glf::section::CsmRender); app->csmRenderer.Draw( app->csmLight, app->gbuffer, viewPos, app->csmParams.blendFactor, app->csmParams.bias, app->renderTarget1); glf::manager::timings->EndSection(glf::section::CsmRender); glBindFramebuffer(GL_FRAMEBUFFER,0); glDisable(GL_STENCIL_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE); // Render dof processing pass glf::manager::timings->StartSection(glf::section::DofProcess); if(app->dofParams.enable) app->dofProcessor.Draw( app->renderTarget1.texture, app->gbuffer.positionTex, view, app->dofParams.nearStart, app->dofParams.nearEnd, app->dofParams.farStart, app->dofParams.farEnd, app->dofParams.maxCoCRadius, app->dofParams.maxBokehRadius, app->dofParams.nSamples, app->dofParams.lumThreshold, app->dofParams.cocThreshold, app->dofParams.bokehDepthCutoff, app->dofParams.poissonFiltering, app->renderTarget2); glf::manager::timings->EndSection(glf::section::DofProcess); // Record performances #if ENABLE_BOKEH_STATISTICS if(app->bokehQuery) { glf::Info("nBokehs : %d",app->dofProcessor.GetDetectedBokehs()); app->bokehQuery = false; } if(app->bokehRecord) { app->bokehFile << app->dofProcessor.GetDetectedBokehs() << " " << glf::manager::timings->GPUTiming(glf::section::DofReset) << " " << glf::manager::timings->GPUTiming(glf::section::DofBlurDepth) << " " << glf::manager::timings->GPUTiming(glf::section::DofDetection) << " " << glf::manager::timings->GPUTiming(glf::section::DofBlur) << " " << glf::manager::timings->GPUTiming(glf::section::DofSynchronization) << " " << glf::manager::timings->GPUTiming(glf::section::DofRendering) << std::endl; app->bokehRecord = false; } #endif glBindFramebuffer(GL_FRAMEBUFFER,0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); // Render post processing pass glf::manager::timings->StartSection(glf::section::PostProcess); if(app->dofParams.enable) app->postProcessor.Draw(app->renderTarget2.texture, app->toneParams.toneExposure, app->renderTarget1); else app->postProcessor.Draw(app->renderTarget1.texture, app->toneParams.toneExposure, app->renderTarget2); glf::manager::timings->EndSection(glf::section::PostProcess); break; case bufferType::GB_POSITION : glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); glBindFramebuffer(GL_FRAMEBUFFER,0); glDepthMask(true); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); app->renderSurface.Draw(app->gbuffer.positionTex); break; case bufferType::GB_NORMAL : glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); app->renderSurface.Draw(app->gbuffer.normalTex); break; case bufferType::GB_DIFFUSE : glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); app->renderSurface.Draw(app->gbuffer.diffuseTex); break; default: assert(false); } glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); if(ctx::drawHelpers) app->helperRenderer.Draw(projection,view,glf::manager::helpers->helpers); if(ctx::drawUI) gui(); if(ctx::drawTimings) app->timingRenderer.Draw(*glf::manager::timings); glDisable(GL_BLEND); glf::CheckError("display"); glf::SwapBuffers(); glf::manager::timings->EndSection(glf::section::Frame); }