Fix Text shader and RenderTexture viewport for SDL2 backend

Text rendering fix:
- Add ShaderType parameter to drawTriangles() to allow explicit shader selection
- Text::draw() now properly uses text shader (alpha-only sampling)
- Previously drawTriangles() always overrode to sprite shader

RenderTexture fix:
- Add pushRenderState/popRenderState to save/restore viewport and projection
- RenderTexture::clear() now sets viewport/projection to FBO dimensions
- RenderTexture::display() restores previous state
- This fixes grid rendering which uses RenderTexture for tile chunks

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
John McCardle 2026-01-31 12:42:12 -05:00
commit e08f189d60
2 changed files with 66 additions and 8 deletions

View file

@ -383,12 +383,56 @@ void SDL2Renderer::clear(float r, float g, float b, float a) {
}
}
void SDL2Renderer::pushRenderState(unsigned int width, unsigned int height) {
RenderState state;
// Save current viewport
glGetIntegerv(GL_VIEWPORT, state.viewport);
// Save current projection
memcpy(state.projection, projectionMatrix_, sizeof(projectionMatrix_));
renderStateStack_.push_back(state);
// Set new viewport and projection for FBO
glViewport(0, 0, width, height);
setProjection(0, static_cast<float>(width), static_cast<float>(height), 0);
}
void SDL2Renderer::popRenderState() {
if (renderStateStack_.empty()) return;
RenderState& state = renderStateStack_.back();
// Restore viewport
glViewport(state.viewport[0], state.viewport[1], state.viewport[2], state.viewport[3]);
// Restore projection
memcpy(projectionMatrix_, state.projection, sizeof(projectionMatrix_));
renderStateStack_.pop_back();
}
void SDL2Renderer::drawTriangles(const float* vertices, size_t vertexCount,
const float* colors, const float* texCoords,
unsigned int textureId) {
unsigned int textureId, ShaderType shaderType) {
if (vertexCount == 0) return;
unsigned int program = textureId ? spriteProgram_ : shapeProgram_;
// Select shader based on type parameter
unsigned int program;
switch (shaderType) {
case ShaderType::Text:
program = textProgram_;
break;
case ShaderType::Sprite:
program = spriteProgram_;
break;
case ShaderType::Shape:
default:
// Auto-select based on texture
program = textureId ? spriteProgram_ : shapeProgram_;
break;
}
glUseProgram(program);
// Set projection uniform
@ -986,10 +1030,12 @@ bool RenderTexture::create(unsigned int width, unsigned int height) {
void RenderTexture::clear(const Color& color) {
SDL2Renderer::getInstance().bindFBO(fboId_);
SDL2Renderer::getInstance().pushRenderState(size_.x, size_.y);
RenderTarget::clear(color);
}
void RenderTexture::display() {
SDL2Renderer::getInstance().popRenderState();
SDL2Renderer::getInstance().unbindFBO();
}
@ -1522,8 +1568,8 @@ void Sprite::draw(RenderTarget& target, RenderStates states) const {
}
// Use sprite shader and draw
glUseProgram(SDL2Renderer::getInstance().getShaderProgram(SDL2Renderer::ShaderType::Sprite));
SDL2Renderer::getInstance().drawTriangles(vertices, 6, colors, texcoords, texture_->getNativeHandle());
SDL2Renderer::getInstance().drawTriangles(vertices, 6, colors, texcoords,
texture_->getNativeHandle(), SDL2Renderer::ShaderType::Sprite);
}
// Static cache for font atlases - keyed by (font data pointer, character size)
@ -1609,12 +1655,12 @@ void Text::draw(RenderTarget& target, RenderStates states) const {
}
if (!vertices.empty()) {
// Use text shader (uses alpha from texture)
glUseProgram(SDL2Renderer::getInstance().getShaderProgram(SDL2Renderer::ShaderType::Text));
// Use text shader (uses alpha from texture, not full RGBA multiply)
SDL2Renderer::getInstance().drawTriangles(
vertices.data(), vertices.size() / 2,
colors.data(), texcoords.data(),
atlas.getTextureId()
atlas.getTextureId(),
SDL2Renderer::ShaderType::Text
);
}
}

View file

@ -82,11 +82,16 @@ public:
// Drawing primitives
void drawTriangles(const float* vertices, size_t vertexCount,
const float* colors, const float* texCoords,
unsigned int textureId = 0);
unsigned int textureId = 0,
ShaderType shaderType = ShaderType::Shape);
// Projection matrix access (for shaders)
const float* getProjectionMatrix() const { return projectionMatrix_; }
// Push/pop viewport and projection for RenderTexture
void pushRenderState(unsigned int width, unsigned int height);
void popRenderState();
private:
SDL2Renderer() = default;
~SDL2Renderer() = default;
@ -107,6 +112,13 @@ private:
// FBO stack for nested render-to-texture
std::vector<unsigned int> fboStack_;
// Viewport/projection stack for nested rendering
struct RenderState {
int viewport[4]; // x, y, width, height
float projection[16];
};
std::vector<RenderState> renderStateStack_;
// Helper functions
bool compileAndLinkProgram(const char* vertexSrc, const char* fragmentSrc, unsigned int& programOut);
unsigned int compileShaderStage(unsigned int type, const char* source);