mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +02:00
Add (low level) functionality to allow rendering 3D Meshes.
- Add love.graphics.setDepthMode(testcomparison, enablewrites). - Add love.graphics.setMeshCullMode. - Add love.graphics.setFrontFaceWinding. Depth testing and depth writes require a depth buffer to work. The mesh cull mode controls whether front/back faces of a mesh are culled. The front face winding determines whether a clockwise or counterclockwise-oriented face in a mesh is considered front facing. --HG-- branch : minor
This commit is contained in:
@@ -68,9 +68,16 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
|
||||
|
||||
if (isPixelFormatDepthStencil(format))
|
||||
{
|
||||
bool hadDepthWrites = gl.hasDepthWrites();
|
||||
if (!hadDepthWrites) // glDepthMask also affects glClear.
|
||||
gl.setDepthWrites(true);
|
||||
|
||||
gl.clearDepth(1.0);
|
||||
glClearStencil(0);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
if (!hadDepthWrites)
|
||||
gl.setDepthWrites(hadDepthWrites);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -128,9 +135,16 @@ static bool createRenderbuffer(int width, int height, int &samples, PixelFormat
|
||||
{
|
||||
if (isPixelFormatDepthStencil(pixelformat))
|
||||
{
|
||||
bool hadDepthWrites = gl.hasDepthWrites();
|
||||
if (!hadDepthWrites) // glDepthMask also affects glClear.
|
||||
gl.setDepthWrites(true);
|
||||
|
||||
gl.clearDepth(1.0);
|
||||
glClearStencil(0);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
if (!hadDepthWrites)
|
||||
gl.setDepthWrites(hadDepthWrites);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -149,7 +149,7 @@ void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelh
|
||||
setScissor(states.back().scissorRect);
|
||||
|
||||
// Set up the projection matrix
|
||||
projectionMatrix = Matrix4::ortho(0.0, (float) width, (float) height, 0.0);
|
||||
projectionMatrix = Matrix4::ortho(0.0, (float) width, (float) height, 0.0, -10.0f, 10.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b
|
||||
|| GLAD_ES_VERSION_3_0 || GLAD_EXT_sRGB)
|
||||
{
|
||||
if (GLAD_VERSION_1_0 || GLAD_EXT_sRGB_write_control)
|
||||
gl.setFramebufferSRGB(isGammaCorrect());
|
||||
gl.setEnableState(OpenGL::ENABLE_FRAMEBUFFER_SRGB, isGammaCorrect());
|
||||
}
|
||||
else
|
||||
setGammaCorrect(false);
|
||||
@@ -316,38 +316,40 @@ void Graphics::setActive(bool enable)
|
||||
active = enable;
|
||||
}
|
||||
|
||||
void Graphics::draw(PrimitiveType primtype, int vertexstart, int vertexcount, int instancecount, const vertex::Attributes &attribs, const vertex::Buffers &buffers, love::graphics::Texture *texture)
|
||||
void Graphics::draw(const DrawCommand &cmd)
|
||||
{
|
||||
gl.prepareDraw();
|
||||
gl.setVertexAttributes(attribs, buffers);
|
||||
gl.bindTextureToUnit(texture, 0, false);
|
||||
gl.setVertexAttributes(*cmd.attributes, *cmd.buffers);
|
||||
gl.bindTextureToUnit(cmd.texture, 0, false);
|
||||
gl.setCullMode(cmd.cullMode);
|
||||
|
||||
GLenum glprimitivetype = OpenGL::getGLPrimitiveType(primtype);
|
||||
GLenum glprimitivetype = OpenGL::getGLPrimitiveType(cmd.primitiveType);
|
||||
|
||||
if (instancecount > 1)
|
||||
glDrawArraysInstanced(glprimitivetype, vertexstart, vertexcount, instancecount);
|
||||
if (cmd.instanceCount > 1)
|
||||
glDrawArraysInstanced(glprimitivetype, cmd.vertexStart, cmd.vertexCount, cmd.instanceCount);
|
||||
else
|
||||
glDrawArrays(glprimitivetype, vertexstart, vertexcount);
|
||||
glDrawArrays(glprimitivetype, cmd.vertexStart, cmd.vertexCount);
|
||||
|
||||
++drawCalls;
|
||||
}
|
||||
|
||||
void Graphics::drawIndexed(PrimitiveType primtype, int indexcount, int instancecount, IndexDataType datatype, Resource *indexbuffer, size_t indexoffset, const vertex::Attributes &attribs, const vertex::Buffers &buffers, love::graphics::Texture *texture)
|
||||
void Graphics::draw(const DrawIndexedCommand &cmd)
|
||||
{
|
||||
gl.prepareDraw();
|
||||
gl.setVertexAttributes(attribs, buffers);
|
||||
gl.bindTextureToUnit(texture, 0, false);
|
||||
gl.setVertexAttributes(*cmd.attributes, *cmd.buffers);
|
||||
gl.bindTextureToUnit(cmd.texture, 0, false);
|
||||
gl.setCullMode(cmd.cullMode);
|
||||
|
||||
const void *gloffset = BUFFER_OFFSET(indexoffset);
|
||||
GLenum glprimitivetype = OpenGL::getGLPrimitiveType(primtype);
|
||||
GLenum gldatatype = OpenGL::getGLIndexDataType(datatype);
|
||||
const void *gloffset = BUFFER_OFFSET(cmd.indexBufferOffset);
|
||||
GLenum glprimitivetype = OpenGL::getGLPrimitiveType(cmd.primitiveType);
|
||||
GLenum gldatatype = OpenGL::getGLIndexDataType(cmd.indexType);
|
||||
|
||||
gl.bindBuffer(BUFFER_INDEX, indexbuffer->getHandle());
|
||||
gl.bindBuffer(BUFFER_INDEX, cmd.indexBuffer->getHandle());
|
||||
|
||||
if (instancecount > 1)
|
||||
glDrawElementsInstanced(glprimitivetype, indexcount, gldatatype, gloffset, instancecount);
|
||||
if (cmd.instanceCount > 1)
|
||||
glDrawElementsInstanced(glprimitivetype, cmd.indexCount, gldatatype, gloffset, cmd.instanceCount);
|
||||
else
|
||||
glDrawElements(glprimitivetype, indexcount, gldatatype, gloffset);
|
||||
glDrawElements(glprimitivetype, cmd.indexCount, gldatatype, gloffset);
|
||||
|
||||
++drawCalls;
|
||||
}
|
||||
@@ -424,20 +426,22 @@ void Graphics::setCanvasInternal(const RenderTargets &rts, int w, int h, int pix
|
||||
|
||||
gl.setViewport({0, 0, pixelw, pixelh});
|
||||
|
||||
// Flip front face winding when rendering to a canvas, since our projection
|
||||
// matrix is flipped.
|
||||
glFrontFace(state.winding == vertex::WINDING_CW ? GL_CCW : GL_CW);
|
||||
|
||||
// Re-apply the scissor if it was active, since the rectangle passed to
|
||||
// glScissor is affected by the viewport dimensions.
|
||||
if (state.scissor)
|
||||
setScissor(state.scissorRect);
|
||||
|
||||
projectionMatrix = Matrix4::ortho(0.0, (float) w, 0.0, (float) h);
|
||||
projectionMatrix = Matrix4::ortho(0.0, (float) w, 0.0, (float) h, -10.0f, 10.0f);
|
||||
|
||||
// Make sure the correct sRGB setting is used when drawing to the canvases.
|
||||
if (GLAD_VERSION_1_0 || GLAD_EXT_sRGB_write_control)
|
||||
{
|
||||
if (hasSRGBcanvas && !gl.hasFramebufferSRGB())
|
||||
gl.setFramebufferSRGB(true);
|
||||
else if (!hasSRGBcanvas && gl.hasFramebufferSRGB())
|
||||
gl.setFramebufferSRGB(false);
|
||||
if (hasSRGBcanvas != gl.isStateEnabled(OpenGL::ENABLE_FRAMEBUFFER_SRGB))
|
||||
gl.setEnableState(OpenGL::ENABLE_FRAMEBUFFER_SRGB, hasSRGBcanvas);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,6 +457,10 @@ void Graphics::setCanvas()
|
||||
flushStreamDraws();
|
||||
endPass();
|
||||
|
||||
// Re-apply the correct front face winding, since it may have been flipped
|
||||
// if we were previously rendering to a canvas.
|
||||
glFrontFace(state.winding == vertex::WINDING_CW ? GL_CW : GL_CCW);
|
||||
|
||||
state.renderTargets = RenderTargetsStrongRef();
|
||||
|
||||
gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, gl.getDefaultFBO());
|
||||
@@ -466,14 +474,12 @@ void Graphics::setCanvas()
|
||||
|
||||
// The projection matrix is flipped compared to rendering to a canvas, due
|
||||
// to OpenGL considering (0,0) bottom-left instead of top-left.
|
||||
projectionMatrix = Matrix4::ortho(0.0, (float) width, (float) height, 0.0);
|
||||
projectionMatrix = Matrix4::ortho(0.0, (float) width, (float) height, 0.0, -10.0f, 10.0f);
|
||||
|
||||
if (GLAD_VERSION_1_0 || GLAD_EXT_sRGB_write_control)
|
||||
{
|
||||
if (isGammaCorrect() && !gl.hasFramebufferSRGB())
|
||||
gl.setFramebufferSRGB(true);
|
||||
else if (!isGammaCorrect() && gl.hasFramebufferSRGB())
|
||||
gl.setFramebufferSRGB(false);
|
||||
if (isGammaCorrect() != gl.isStateEnabled(OpenGL::ENABLE_FRAMEBUFFER_SRGB))
|
||||
gl.setEnableState(OpenGL::ENABLE_FRAMEBUFFER_SRGB, isGammaCorrect());
|
||||
}
|
||||
|
||||
canvasSwitchCount++;
|
||||
@@ -571,8 +577,13 @@ void Graphics::clear(OptionalColorf c, OptionalInt stencil, OptionalDouble depth
|
||||
flags |= GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
|
||||
bool hadDepthWrites = gl.hasDepthWrites();
|
||||
|
||||
if (depth.hasValue)
|
||||
{
|
||||
if (!hadDepthWrites) // glDepthMask also affects glClear.
|
||||
gl.setDepthWrites(true);
|
||||
|
||||
gl.clearDepth(depth.value);
|
||||
flags |= GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
@@ -580,6 +591,9 @@ void Graphics::clear(OptionalColorf c, OptionalInt stencil, OptionalDouble depth
|
||||
if (flags != 0)
|
||||
glClear(flags);
|
||||
|
||||
if (depth.hasValue && !hadDepthWrites)
|
||||
gl.setDepthWrites(hadDepthWrites);
|
||||
|
||||
if (c.hasValue && gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
|
||||
{
|
||||
// This seems to be enough to fix the bug for me. Other methods I've
|
||||
@@ -652,8 +666,13 @@ void Graphics::clear(const std::vector<OptionalColorf> &colors, OptionalInt sten
|
||||
flags |= GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
|
||||
bool hadDepthWrites = gl.hasDepthWrites();
|
||||
|
||||
if (depth.hasValue)
|
||||
{
|
||||
if (!hadDepthWrites) // glDepthMask also affects glClear.
|
||||
gl.setDepthWrites(true);
|
||||
|
||||
gl.clearDepth(depth.value);
|
||||
flags |= GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
@@ -661,6 +680,9 @@ void Graphics::clear(const std::vector<OptionalColorf> &colors, OptionalInt sten
|
||||
if (flags != 0)
|
||||
glClear(flags);
|
||||
|
||||
if (depth.hasValue && !hadDepthWrites)
|
||||
gl.setDepthWrites(hadDepthWrites);
|
||||
|
||||
if (gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
|
||||
{
|
||||
// This seems to be enough to fix the bug for me. Other methods I've
|
||||
@@ -986,7 +1008,8 @@ void Graphics::setScissor(const Rect &rect)
|
||||
|
||||
DisplayState &state = states.back();
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
if (!gl.isStateEnabled(OpenGL::ENABLE_SCISSOR_TEST))
|
||||
gl.setEnableState(OpenGL::ENABLE_SCISSOR_TEST, true);
|
||||
|
||||
double dpiscale = getCurrentDPIScale();
|
||||
|
||||
@@ -1009,7 +1032,9 @@ void Graphics::setScissor()
|
||||
flushStreamDraws();
|
||||
|
||||
states.back().scissor = false;
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
if (gl.isStateEnabled(OpenGL::ENABLE_SCISSOR_TEST))
|
||||
gl.setEnableState(OpenGL::ENABLE_SCISSOR_TEST, false);
|
||||
}
|
||||
|
||||
void Graphics::drawToStencilBuffer(StencilAction action, int value)
|
||||
@@ -1055,7 +1080,9 @@ void Graphics::drawToStencilBuffer(StencilAction action, int value)
|
||||
}
|
||||
|
||||
// The stencil test must be enabled in order to write to the stencil buffer.
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
if (!gl.isStateEnabled(OpenGL::ENABLE_STENCIL_TEST))
|
||||
gl.setEnableState(OpenGL::ENABLE_STENCIL_TEST, true);
|
||||
|
||||
glStencilFunc(GL_ALWAYS, value, 0xFFFFFFFF);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, glaction);
|
||||
}
|
||||
@@ -1093,7 +1120,8 @@ void Graphics::setStencilTest(CompareMode compare, int value)
|
||||
|
||||
if (compare == COMPARE_ALWAYS)
|
||||
{
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
if (gl.isStateEnabled(OpenGL::ENABLE_STENCIL_TEST))
|
||||
gl.setEnableState(OpenGL::ENABLE_STENCIL_TEST, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1107,14 +1135,48 @@ void Graphics::setStencilTest(CompareMode compare, int value)
|
||||
**/
|
||||
GLenum glcompare = OpenGL::getGLCompareMode(getReversedCompareMode(compare));
|
||||
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
if (!gl.isStateEnabled(OpenGL::ENABLE_STENCIL_TEST))
|
||||
gl.setEnableState(OpenGL::ENABLE_STENCIL_TEST, true);
|
||||
|
||||
glStencilFunc(glcompare, value, 0xFFFFFFFF);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
}
|
||||
|
||||
void Graphics::setStencilTest()
|
||||
void Graphics::setDepthMode(CompareMode compare, bool write)
|
||||
{
|
||||
setStencilTest(COMPARE_ALWAYS, 0);
|
||||
DisplayState &state = states.back();
|
||||
|
||||
if (state.depthTest != compare || state.depthWrite != write)
|
||||
flushStreamDraws();
|
||||
|
||||
state.depthTest = compare;
|
||||
state.depthWrite = write;
|
||||
|
||||
bool depthenable = compare != COMPARE_ALWAYS || write;
|
||||
|
||||
if (depthenable != gl.isStateEnabled(OpenGL::ENABLE_DEPTH_TEST))
|
||||
gl.setEnableState(OpenGL::ENABLE_DEPTH_TEST, depthenable);
|
||||
|
||||
if (depthenable)
|
||||
{
|
||||
glDepthFunc(OpenGL::getGLCompareMode(compare));
|
||||
glDepthMask(write ? GL_TRUE : GL_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::setFrontFaceWinding(vertex::Winding winding)
|
||||
{
|
||||
DisplayState &state = states.back();
|
||||
|
||||
if (state.winding != winding)
|
||||
flushStreamDraws();
|
||||
|
||||
state.winding = winding;
|
||||
|
||||
if (isCanvasActive())
|
||||
winding = winding == vertex::WINDING_CW ? vertex::WINDING_CCW : vertex::WINDING_CW;
|
||||
|
||||
glFrontFace(winding == vertex::WINDING_CW ? GL_CW : GL_CCW);
|
||||
}
|
||||
|
||||
void Graphics::setColor(Colorf c)
|
||||
@@ -1142,12 +1204,6 @@ void Graphics::setBlendMode(BlendMode mode, BlendAlpha alphamode)
|
||||
if (mode != states.back().blendMode || alphamode != states.back().blendAlphaMode)
|
||||
flushStreamDraws();
|
||||
|
||||
GLenum func = GL_FUNC_ADD;
|
||||
GLenum srcRGB = GL_ONE;
|
||||
GLenum srcA = GL_ONE;
|
||||
GLenum dstRGB = GL_ZERO;
|
||||
GLenum dstA = GL_ZERO;
|
||||
|
||||
if (mode == BLEND_LIGHTEN || mode == BLEND_DARKEN)
|
||||
{
|
||||
if (!capabilities.features[FEATURE_LIGHTEN])
|
||||
@@ -1170,6 +1226,12 @@ void Graphics::setBlendMode(BlendMode mode, BlendAlpha alphamode)
|
||||
}
|
||||
}
|
||||
|
||||
GLenum func = GL_FUNC_ADD;
|
||||
GLenum srcRGB = GL_ONE;
|
||||
GLenum srcA = GL_ONE;
|
||||
GLenum dstRGB = GL_ZERO;
|
||||
GLenum dstA = GL_ZERO;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case BLEND_ALPHA:
|
||||
|
||||
@@ -69,8 +69,8 @@ public:
|
||||
|
||||
void setActive(bool active) override;
|
||||
|
||||
void draw(PrimitiveType primtype, int vertexstart, int vertexcount, int instancecount, const vertex::Attributes &attribs, const vertex::Buffers &buffers, Texture *texture) override;
|
||||
void drawIndexed(PrimitiveType primtype, int indexcount, int instancecount, IndexDataType datatype, Resource *indexbuffer, size_t indexoffset, const vertex::Attributes &attribs, const vertex::Buffers &buffers, Texture *texture) override;
|
||||
void draw(const DrawCommand &cmd) override;
|
||||
void draw(const DrawIndexedCommand &cmd) override;
|
||||
|
||||
void clear(OptionalColorf color, OptionalInt stencil, OptionalDouble depth) override;
|
||||
void clear(const std::vector<OptionalColorf> &colors, OptionalInt stencil, OptionalDouble depth) override;
|
||||
@@ -90,7 +90,10 @@ public:
|
||||
void stopDrawToStencilBuffer() override;
|
||||
|
||||
void setStencilTest(CompareMode compare, int value) override;
|
||||
void setStencilTest() override;
|
||||
|
||||
void setDepthMode(CompareMode compare, bool write) override;
|
||||
|
||||
void setFrontFaceWinding(vertex::Winding winding) override;
|
||||
|
||||
void setColorMask(ColorMask mask) override;
|
||||
|
||||
|
||||
@@ -191,13 +191,22 @@ void OpenGL::setupContext()
|
||||
state.boundFramebuffers[i] = std::numeric_limits<GLuint>::max();
|
||||
bindFramebuffer(FRAMEBUFFER_ALL, getDefaultFBO());
|
||||
|
||||
setEnableState(ENABLE_DEPTH_TEST, state.enableState[ENABLE_DEPTH_TEST]);
|
||||
setEnableState(ENABLE_STENCIL_TEST, state.enableState[ENABLE_STENCIL_TEST]);
|
||||
setEnableState(ENABLE_SCISSOR_TEST, state.enableState[ENABLE_SCISSOR_TEST]);
|
||||
setEnableState(ENABLE_FACE_CULL, state.enableState[ENABLE_FACE_CULL]);
|
||||
|
||||
if (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB
|
||||
|| GLAD_EXT_sRGB_write_control)
|
||||
{
|
||||
state.framebufferSRGBEnabled = (glIsEnabled(GL_FRAMEBUFFER_SRGB) == GL_TRUE);
|
||||
setEnableState(ENABLE_FRAMEBUFFER_SRGB, state.enableState[ENABLE_FRAMEBUFFER_SRGB]);
|
||||
}
|
||||
else
|
||||
state.framebufferSRGBEnabled = false;
|
||||
state.enableState[ENABLE_FRAMEBUFFER_SRGB] = false;
|
||||
|
||||
GLint faceCull = GL_BACK;
|
||||
glGetIntegerv(GL_CULL_FACE_MODE, &faceCull);
|
||||
state.faceCullMode = faceCull;
|
||||
|
||||
for (int i = 0; i < (int) BUFFER_MAX_ENUM; i++)
|
||||
{
|
||||
@@ -228,6 +237,8 @@ void OpenGL::setupContext()
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
state.curTextureUnit = 0;
|
||||
|
||||
setDepthWrites(state.depthWritesEnabled);
|
||||
|
||||
createDefaultTexture();
|
||||
|
||||
contextInitialized = true;
|
||||
@@ -673,6 +684,24 @@ void OpenGL::setVertexAttributes(const vertex::Attributes &attributes, const ver
|
||||
glVertexAttrib4f(ATTRIB_COLOR, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
void OpenGL::setCullMode(CullMode mode)
|
||||
{
|
||||
bool enabled = mode != CULL_NONE;
|
||||
|
||||
if (enabled != isStateEnabled(ENABLE_FACE_CULL))
|
||||
setEnableState(ENABLE_FACE_CULL, enabled);
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
GLenum glmode = mode == CULL_BACK ? GL_BACK : GL_FRONT;
|
||||
if (glmode != state.faceCullMode)
|
||||
{
|
||||
glCullFace(glmode);
|
||||
state.faceCullMode = glmode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGL::clearDepth(double value)
|
||||
{
|
||||
if (GLAD_ES_VERSION_2_0)
|
||||
@@ -729,19 +758,42 @@ float OpenGL::getPointSize() const
|
||||
return state.pointSize;
|
||||
}
|
||||
|
||||
void OpenGL::setFramebufferSRGB(bool enable)
|
||||
void OpenGL::setEnableState(EnableState enablestate, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
else
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
GLenum glstate = GL_NONE;
|
||||
|
||||
state.framebufferSRGBEnabled = enable;
|
||||
switch (enablestate)
|
||||
{
|
||||
case ENABLE_DEPTH_TEST:
|
||||
glstate = GL_DEPTH_TEST;
|
||||
break;
|
||||
case ENABLE_STENCIL_TEST:
|
||||
glstate = GL_STENCIL_TEST;
|
||||
break;
|
||||
case ENABLE_SCISSOR_TEST:
|
||||
glstate = GL_SCISSOR_TEST;
|
||||
break;
|
||||
case ENABLE_FACE_CULL:
|
||||
glstate = GL_CULL_FACE;
|
||||
break;
|
||||
case ENABLE_FRAMEBUFFER_SRGB:
|
||||
glstate = GL_FRAMEBUFFER_SRGB;
|
||||
break;
|
||||
case ENABLE_MAX_ENUM:
|
||||
break;
|
||||
}
|
||||
|
||||
if (enable)
|
||||
glEnable(glstate);
|
||||
else
|
||||
glDisable(glstate);
|
||||
|
||||
state.enableState[enablestate] = enable;
|
||||
}
|
||||
|
||||
bool OpenGL::hasFramebufferSRGB() const
|
||||
bool OpenGL::isStateEnabled(EnableState enablestate) const
|
||||
{
|
||||
return state.framebufferSRGBEnabled;
|
||||
return state.enableState[enablestate];
|
||||
}
|
||||
|
||||
void OpenGL::bindFramebuffer(FramebufferTarget target, GLuint framebuffer)
|
||||
@@ -816,6 +868,17 @@ void OpenGL::framebufferTexture(GLenum attachment, TextureType texType, GLuint t
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGL::setDepthWrites(bool enable)
|
||||
{
|
||||
glDepthMask(enable ? GL_TRUE : GL_FALSE);
|
||||
state.depthWritesEnabled = enable;
|
||||
}
|
||||
|
||||
bool OpenGL::hasDepthWrites() const
|
||||
{
|
||||
return state.depthWritesEnabled;
|
||||
}
|
||||
|
||||
void OpenGL::useProgram(GLuint program)
|
||||
{
|
||||
glUseProgram(program);
|
||||
@@ -954,7 +1017,6 @@ GLint OpenGL::getGLWrapMode(Texture::WrapMode wmode)
|
||||
case Texture::WRAP_MIRRORED_REPEAT:
|
||||
return GL_MIRRORED_REPEAT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GLint OpenGL::getGLCompareMode(CompareMode mode)
|
||||
@@ -975,6 +1037,8 @@ GLint OpenGL::getGLCompareMode(CompareMode mode)
|
||||
return GL_NOTEQUAL;
|
||||
case COMPARE_ALWAYS:
|
||||
return GL_ALWAYS;
|
||||
case COMPARE_NEVER:
|
||||
return GL_NEVER;
|
||||
default:
|
||||
return GL_NEVER;
|
||||
}
|
||||
|
||||
@@ -92,6 +92,16 @@ public:
|
||||
FRAMEBUFFER_ALL = (FRAMEBUFFER_READ | FRAMEBUFFER_DRAW),
|
||||
};
|
||||
|
||||
enum EnableState
|
||||
{
|
||||
ENABLE_DEPTH_TEST,
|
||||
ENABLE_STENCIL_TEST,
|
||||
ENABLE_SCISSOR_TEST,
|
||||
ENABLE_FACE_CULL,
|
||||
ENABLE_FRAMEBUFFER_SRGB,
|
||||
ENABLE_MAX_ENUM
|
||||
};
|
||||
|
||||
struct TextureFormat
|
||||
{
|
||||
GLenum internalformat = 0;
|
||||
@@ -204,6 +214,11 @@ public:
|
||||
**/
|
||||
void setVertexAttributes(const vertex::Attributes &attributes, const vertex::Buffers &buffers);
|
||||
|
||||
/**
|
||||
* Wrapper for glCullFace which eliminates redundant state setting.
|
||||
**/
|
||||
void setCullMode(CullMode mode);
|
||||
|
||||
/**
|
||||
* Wrapper for glClearDepth and glClearDepthf.
|
||||
**/
|
||||
@@ -236,10 +251,10 @@ public:
|
||||
float getPointSize() const;
|
||||
|
||||
/**
|
||||
* Calls glEnable/glDisable(GL_FRAMEBUFFER_SRGB).
|
||||
* State-tracked version of glEnable.
|
||||
**/
|
||||
void setFramebufferSRGB(bool enable);
|
||||
bool hasFramebufferSRGB() const;
|
||||
void setEnableState(EnableState state, bool enable);
|
||||
bool isStateEnabled(EnableState state) const;
|
||||
|
||||
/**
|
||||
* Binds a Framebuffer Object to the specified target.
|
||||
@@ -250,6 +265,12 @@ public:
|
||||
|
||||
void framebufferTexture(GLenum attachment, TextureType texType, GLuint texture, int level, int layer = 0, int face = 0);
|
||||
|
||||
/**
|
||||
* Calls glDepthMask.
|
||||
**/
|
||||
void setDepthWrites(bool enable);
|
||||
bool hasDepthWrites() const;
|
||||
|
||||
/**
|
||||
* Calls glUseProgram.
|
||||
**/
|
||||
@@ -415,7 +436,10 @@ private:
|
||||
// Texture unit state (currently bound texture for each texture unit.)
|
||||
std::vector<GLuint> boundTextures[TEXTURE_MAX_ENUM];
|
||||
|
||||
// Currently active texture unit.
|
||||
bool enableState[ENABLE_MAX_ENUM];
|
||||
|
||||
GLenum faceCullMode;
|
||||
|
||||
int curTextureUnit;
|
||||
|
||||
uint32 enabledAttribArrays;
|
||||
@@ -429,9 +453,9 @@ private:
|
||||
|
||||
float pointSize;
|
||||
|
||||
GLuint boundFramebuffers[2];
|
||||
bool depthWritesEnabled;
|
||||
|
||||
bool framebufferSRGBEnabled;
|
||||
GLuint boundFramebuffers[2];
|
||||
|
||||
GLuint defaultTexture[TEXTURE_MAX_ENUM];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user