IrrlichtMt: Move OpenGL 3+ transformation matrix to shaders (#15591)

This replaces annoying calculations on C++-side and eases the
implementation of 2D geometry batch rendering a lot.
This commit is contained in:
SmallJoker 2024-12-28 22:04:05 +01:00 committed by GitHub
parent 412cc96bc9
commit 35bc217ba8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 107 additions and 97 deletions

@ -9,6 +9,7 @@ attribute vec2 inTexCoord0;
/* Uniforms */
uniform float uThickness;
uniform mat4 uProjection;
/* Varyings */
@ -17,7 +18,7 @@ varying vec4 vVertexColor;
void main()
{
gl_Position = inVertexPosition;
gl_Position = uProjection * inVertexPosition;
gl_PointSize = uThickness;
vTextureCoord = inTexCoord0;
vVertexColor = inVertexColor.bgra;

@ -689,58 +689,32 @@ void COpenGL3DriverBase::drawVertexPrimitiveList(const void *vertices, u32 verte
setRenderStates3DMode();
auto &vTypeDesc = getVertexTypeDescription(vType);
beginDraw(vTypeDesc, reinterpret_cast<uintptr_t>(vertices));
GLenum indexSize = 0;
switch (iType) {
case (EIT_16BIT): {
indexSize = GL_UNSIGNED_SHORT;
break;
}
case (EIT_32BIT): {
indexSize = GL_UNSIGNED_INT;
break;
}
}
switch (pType) {
case scene::EPT_POINTS:
case scene::EPT_POINT_SPRITES:
GL.DrawArrays(GL_POINTS, 0, primitiveCount);
break;
case scene::EPT_LINE_STRIP:
GL.DrawElements(GL_LINE_STRIP, primitiveCount + 1, indexSize, indexList);
break;
case scene::EPT_LINE_LOOP:
GL.DrawElements(GL_LINE_LOOP, primitiveCount, indexSize, indexList);
break;
case scene::EPT_LINES:
GL.DrawElements(GL_LINES, primitiveCount * 2, indexSize, indexList);
break;
case scene::EPT_TRIANGLE_STRIP:
GL.DrawElements(GL_TRIANGLE_STRIP, primitiveCount + 2, indexSize, indexList);
break;
case scene::EPT_TRIANGLE_FAN:
GL.DrawElements(GL_TRIANGLE_FAN, primitiveCount + 2, indexSize, indexList);
break;
case scene::EPT_TRIANGLES:
GL.DrawElements((LastMaterial.Wireframe) ? GL_LINES : (LastMaterial.PointCloud) ? GL_POINTS
: GL_TRIANGLES,
primitiveCount * 3, indexSize, indexList);
break;
default:
break;
}
endDraw(vTypeDesc);
drawGeneric(vertices, indexList, primitiveCount, vType, pType, iType);
}
//! draws a vertex primitive list in 2d
void COpenGL3DriverBase::draw2DVertexPrimitiveList(const void *vertices, u32 vertexCount,
const void *indexList, u32 primitiveCount,
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType)
{
os::Printer::log("draw2DVertexPrimitiveList unimplemented", ELL_ERROR);
if (!primitiveCount || !vertexCount)
return;
if (!vertices)
return;
if (!checkPrimitiveCount(primitiveCount))
return;
CNullDriver::draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType);
setRenderStates2DMode(
Material.MaterialType == EMT_TRANSPARENT_VERTEX_ALPHA,
Material.getTexture(0),
Material.MaterialType == EMT_TRANSPARENT_ALPHA_CHANNEL
);
drawGeneric(vertices, indexList, primitiveCount, vType, pType, iType);
}
void COpenGL3DriverBase::draw2DImage(const video::ITexture *texture, const core::position2d<s32> &destPos,
@ -803,10 +777,10 @@ void COpenGL3DriverBase::draw2DImage(const video::ITexture *texture, const core:
clipRect->getWidth(), clipRect->getHeight());
}
f32 left = (f32)destRect.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
f32 right = (f32)destRect.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
f32 down = 2.f - (f32)destRect.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
f32 top = 2.f - (f32)destRect.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
f32 left = (f32)destRect.UpperLeftCorner.X;
f32 right = (f32)destRect.LowerRightCorner.X;
f32 down = (f32)destRect.LowerRightCorner.Y;
f32 top = (f32)destRect.UpperLeftCorner.Y;
S3DVertex vertices[4];
vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, useColor[0], tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
@ -903,10 +877,10 @@ void COpenGL3DriverBase::draw2DImageBatch(const video::ITexture *texture,
const core::rect<s32> poss(targetPos, sourceSize);
f32 left = (f32)poss.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
f32 right = (f32)poss.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
f32 down = 2.f - (f32)poss.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
f32 top = 2.f - (f32)poss.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
f32 left = (f32)poss.UpperLeftCorner.X;
f32 right = (f32)poss.LowerRightCorner.X;
f32 down = (f32)poss.LowerRightCorner.Y;
f32 top = (f32)poss.UpperLeftCorner.Y;
vtx.emplace_back(left, top, 0.0f,
0.0f, 0.0f, 0.0f, color,
@ -935,33 +909,7 @@ void COpenGL3DriverBase::draw2DRectangle(SColor color,
const core::rect<s32> &position,
const core::rect<s32> *clip)
{
chooseMaterial2D();
setMaterialTexture(0, 0);
setRenderStates2DMode(color.getAlpha() < 255, false, false);
core::rect<s32> pos = position;
if (clip)
pos.clipAgainst(*clip);
if (!pos.isValid())
return;
const core::dimension2d<u32> &renderTargetSize = getCurrentRenderTargetSize();
f32 left = (f32)pos.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
f32 right = (f32)pos.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
f32 down = 2.f - (f32)pos.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
f32 top = 2.f - (f32)pos.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
S3DVertex vertices[4];
vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, color, 0, 0);
vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, color, 0, 0);
vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, color, 0, 0);
vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, color, 0, 0);
drawQuad(vtPrimitive, vertices);
draw2DRectangle(position, color, color, color, color, clip);
}
//! draw an 2d rectangle
@ -987,18 +935,16 @@ void COpenGL3DriverBase::draw2DRectangle(const core::rect<s32> &position,
colorRightDown.getAlpha() < 255,
false, false);
const core::dimension2d<u32> &renderTargetSize = getCurrentRenderTargetSize();
f32 left = (f32)pos.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
f32 right = (f32)pos.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;
f32 down = 2.f - (f32)pos.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
f32 top = 2.f - (f32)pos.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
f32 left = (f32)pos.UpperLeftCorner.X;
f32 right = (f32)pos.LowerRightCorner.X;
f32 down = (f32)pos.LowerRightCorner.Y;
f32 top = (f32)pos.UpperLeftCorner.Y;
S3DVertex vertices[4];
vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, colorLeftUp, 0, 0);
vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, colorRightUp, 0, 0);
vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, colorLeftUp, 0, 0);
vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, colorRightUp, 0, 0);
vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, colorRightDown, 0, 0);
vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, colorLeftDown, 0, 0);
vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, colorLeftDown, 0, 0);
drawQuad(vtPrimitive, vertices);
}
@ -1013,12 +959,10 @@ void COpenGL3DriverBase::draw2DLine(const core::position2d<s32> &start,
setRenderStates2DMode(color.getAlpha() < 255, false, false);
const core::dimension2d<u32> &renderTargetSize = getCurrentRenderTargetSize();
f32 startX = (f32)start.X / (f32)renderTargetSize.Width * 2.f - 1.f;
f32 endX = (f32)end.X / (f32)renderTargetSize.Width * 2.f - 1.f;
f32 startY = 2.f - (f32)start.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
f32 endY = 2.f - (f32)end.Y / (f32)renderTargetSize.Height * 2.f - 1.f;
f32 startX = (f32)start.X;
f32 endX = (f32)end.X;
f32 startY = (f32)start.Y;
f32 endY = (f32)end.Y;
S3DVertex vertices[2];
vertices[0] = S3DVertex(startX, startY, 0, 0, 0, 1, color, 0, 0);
@ -1047,6 +991,55 @@ void COpenGL3DriverBase::drawElements(GLenum primitiveType, const VertexType &ve
endDraw(vertexType);
}
void COpenGL3DriverBase::drawGeneric(const void *vertices, const void *indexList,
u32 primitiveCount,
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType)
{
auto &vTypeDesc = getVertexTypeDescription(vType);
beginDraw(vTypeDesc, reinterpret_cast<uintptr_t>(vertices));
GLenum indexSize = 0;
switch (iType) {
case EIT_16BIT:
indexSize = GL_UNSIGNED_SHORT;
break;
case EIT_32BIT:
indexSize = GL_UNSIGNED_INT;
break;
}
switch (pType) {
case scene::EPT_POINTS:
case scene::EPT_POINT_SPRITES:
GL.DrawArrays(GL_POINTS, 0, primitiveCount);
break;
case scene::EPT_LINE_STRIP:
GL.DrawElements(GL_LINE_STRIP, primitiveCount + 1, indexSize, indexList);
break;
case scene::EPT_LINE_LOOP:
GL.DrawElements(GL_LINE_LOOP, primitiveCount, indexSize, indexList);
break;
case scene::EPT_LINES:
GL.DrawElements(GL_LINES, primitiveCount * 2, indexSize, indexList);
break;
case scene::EPT_TRIANGLE_STRIP:
GL.DrawElements(GL_TRIANGLE_STRIP, primitiveCount + 2, indexSize, indexList);
break;
case scene::EPT_TRIANGLE_FAN:
GL.DrawElements(GL_TRIANGLE_FAN, primitiveCount + 2, indexSize, indexList);
break;
case scene::EPT_TRIANGLES:
GL.DrawElements((LastMaterial.Wireframe) ? GL_LINES : (LastMaterial.PointCloud) ? GL_POINTS
: GL_TRIANGLES,
primitiveCount * 3, indexSize, indexList);
break;
default:
break;
}
endDraw(vTypeDesc);
}
void COpenGL3DriverBase::beginDraw(const VertexType &vertexType, uintptr_t verticesBase)
{
for (auto &attr : vertexType) {

@ -316,6 +316,9 @@ protected:
void drawElements(GLenum primitiveType, const VertexType &vertexType, const void *vertices, int vertexCount, const u16 *indices, int indexCount);
void drawElements(GLenum primitiveType, const VertexType &vertexType, uintptr_t vertices, uintptr_t indices, int indexCount);
void drawGeneric(const void *vertices, const void *indexList, u32 primitiveCount,
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType);
void beginDraw(const VertexType &vertexType, uintptr_t verticesBase);
void endDraw(const VertexType &vertexType);

@ -32,6 +32,7 @@ COpenGL3Renderer2D::COpenGL3Renderer2D(const c8 *vertexShaderProgram, const c8 *
// These states don't change later.
ProjectionID = getPixelShaderConstantID("uProjection");
ThicknessID = getPixelShaderConstantID("uThickness");
if (WithTexture) {
TextureUsageID = getPixelShaderConstantID("uTextureUsage");
@ -62,6 +63,17 @@ void COpenGL3Renderer2D::OnSetMaterial(const video::SMaterial &material,
f32 Thickness = (material.Thickness > 0.f) ? material.Thickness : 1.f;
setPixelShaderConstant(ThicknessID, &Thickness, 1);
{
// Update projection matrix
const core::dimension2d<u32> renderTargetSize = Driver->getCurrentRenderTargetSize();
core::matrix4 proj;
float xInv2 = 2.0f / renderTargetSize.Width;
float yInv2 = 2.0f / renderTargetSize.Height;
proj.setScale({ xInv2, -yInv2, 0.0f });
proj.setTranslation({ -1.0f, 1.0f, 0.0f });
setPixelShaderConstant(ProjectionID, proj.pointer(), 4 * 4);
}
if (WithTexture) {
s32 TextureUsage = material.TextureLayers[0].Texture ? 1 : 0;
setPixelShaderConstant(TextureUsageID, &TextureUsage, 1);

@ -24,6 +24,7 @@ public:
protected:
bool WithTexture;
s32 ProjectionID;
s32 ThicknessID;
s32 TextureUsageID;
};