Remove other usages of built-in GL matrices

Primarily for the FoW rendering, which now also uses (simple) shaders
without ftransform() everywhere. This also removes all GLU calls.
shapetextures
Armin Burgmeier 2015-12-31 17:28:05 -08:00
parent eaf66850b1
commit 8766f5123b
13 changed files with 129 additions and 69 deletions

View File

@ -0,0 +1,24 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2015, The OpenClonk Team and contributors
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
*/
// Default Vertex Shader for the landscape.
uniform mat4 projectionMatrix;
slice(position)
{
// model-view matrix is always the identity matrix
gl_Position = projectionMatrix * gl_Vertex;
}

View File

@ -169,43 +169,10 @@ bool CStdGL::UpdateClipper()
ClipAll=false;
// set it
glViewport(clipRect.x, RenderTarget->Hgt-clipRect.y-clipRect.Hgt, clipRect.Wdt, clipRect.Hgt);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D((GLdouble) clipRect.x, (GLdouble) (clipRect.x + clipRect.Wdt), (GLdouble) (clipRect.y + clipRect.Hgt), (GLdouble) clipRect.y);
UpdateProjectionMatrix();
ProjectionMatrix = StdProjectionMatrix::Orthographic(clipRect.x, clipRect.x + clipRect.Wdt, clipRect.y + clipRect.Hgt, clipRect.y);
return true;
}
void CStdGL::UpdateProjectionMatrix()
{
const C4Rect clipRect = GetClipRect();
const float left = clipRect.x;
const float right = clipRect.x + clipRect.Wdt;
const float bottom = clipRect.y + clipRect.Hgt;
const float top = clipRect.y;
const float nearVal = -1.0f;
const float farVal = +1.0f;
ProjectionMatrix(0,0) = 2.0f / (right - left);
ProjectionMatrix(0,1) = 0.0f;
ProjectionMatrix(0,2) = 0.0f;
ProjectionMatrix(0,3) = -(right + left) / (right - left);
ProjectionMatrix(1,0) = 0.0f;
ProjectionMatrix(1,1) = 2.0f / (top - bottom);
ProjectionMatrix(1,2) = 0.0f;
ProjectionMatrix(1,3) = -(top + bottom) / (top - bottom);
ProjectionMatrix(2,0) = 0.0f;
ProjectionMatrix(2,1) = 0.0f;
ProjectionMatrix(2,2) = -2.0f / (farVal - nearVal);
ProjectionMatrix(2,3) = -(farVal + nearVal) / (farVal - nearVal);
ProjectionMatrix(3,0) = 0.0f;
ProjectionMatrix(3,1) = 0.0f;
ProjectionMatrix(3,2) = 0.0f;
ProjectionMatrix(3,3) = 1.0f;
}
bool CStdGL::PrepareRendering(C4Surface * sfcToSurface)
{
// call from gfx thread only!
@ -287,12 +254,12 @@ bool CStdGL::PrepareSpriteShader(C4Shader& shader, const char* name, int ssc, C4
for (const char* const* define = additionalDefines; *define != NULL; ++define)
shader.AddFragmentSlice(-1, FormatString("#define %s", *define).getData());
shader.LoadSlices(pGroups, "CommonShader.glsl");
shader.LoadSlices(pGroups, "ObjectShader.glsl");
shader.LoadFragmentSlices(pGroups, "CommonShader.glsl");
shader.LoadFragmentSlices(pGroups, "ObjectShader.glsl");
if (additionalSlices)
for (const char* const* slice = additionalSlices; *slice != NULL; ++slice)
shader.LoadSlices(pGroups, *slice);
shader.LoadFragmentSlices(pGroups, *slice);
if (!shader.Init(name, uniformNames))
{

View File

@ -165,7 +165,7 @@ public:
virtual bool OnResolutionChanged(unsigned int iXRes, unsigned int iYRes); // reinit clipper for new resolution
// Clipper
bool UpdateClipper(); // set current clipper to render target
void UpdateProjectionMatrix();
const StdProjectionMatrix& GetProjectionMatrix() const { return ProjectionMatrix; }
virtual bool PrepareMaterial(StdMeshMatManager& mat_manager, StdMeshMaterialLoader& loader, StdMeshMaterial& mat);
// Surface
virtual bool PrepareRendering(C4Surface * sfcToSurface); // check if/make rendering possible to given surface

View File

@ -77,6 +77,16 @@ void C4Shader::AddFragmentSlices(const char *szWhat, const char *szText, const c
AddSlices(FragmentSlices, szWhat, szText, szSource, iSourceTime);
}
bool C4Shader::LoadFragmentSlices(C4GroupSet *pGroups, const char *szFile)
{
return LoadSlices(FragmentSlices, pGroups, szFile);
}
bool C4Shader::LoadVertexSlices(C4GroupSet *pGroups, const char *szFile)
{
return LoadSlices(VertexSlices, pGroups, szFile);
}
void C4Shader::AddSlice(ShaderSliceList& slices, int iPos, const char *szText, const char *szSource, int iSourceTime)
{
ShaderSlice Slice;
@ -240,7 +250,7 @@ int C4Shader::ParsePosition(const char *szWhat, const char **ppPos)
return iPosition;
}
bool C4Shader::LoadSlices(C4GroupSet *pGroups, const char *szFile)
bool C4Shader::LoadSlices(ShaderSliceList& slices, C4GroupSet *pGroups, const char *szFile)
{
// Search for our shaders
C4Group *pGroup = pGroups->FindEntry(szFile);
@ -257,15 +267,10 @@ bool C4Shader::LoadSlices(C4GroupSet *pGroups, const char *szFile)
iSourceTime = FileTime(Source.getData());
// Load
StdStrBuf What = FormatString("file %s", Config.AtRelativePath(Source.getData()));
AddFragmentSlices(What.getData(), Shader.getData(), Source.getData(), iSourceTime);
AddSlices(slices, What.getData(), Shader.getData(), Source.getData(), iSourceTime);
return true;
}
void C4Shader::AddVertexDefaults()
{
AddVertexSlice(C4Shader_Vertex_PositionPos, "gl_Position = ftransform();\n");
}
#ifndef USE_CONSOLE
GLenum C4Shader::AddTexCoord(const char *szName)
{

View File

@ -137,10 +137,8 @@ public:
void AddFragmentSlice(int iPos, const char *szText, const char *szSource = "", int iFileTime = 0);
void AddVertexSlices(const char *szWhat, const char *szText, const char *szSource = "", int iFileTime = 0);
void AddFragmentSlices(const char *szWhat, const char *szText, const char *szSource = "", int iFileTime = 0);
bool LoadSlices(C4GroupSet *pGroupSet, const char *szFile);
// Add default vertex code (2D - no transformation)
void AddVertexDefaults();
bool LoadFragmentSlices(C4GroupSet *pGroupSet, const char *szFile);
bool LoadVertexSlices(C4GroupSet *pGroupSet, const char *szFile);
#ifndef USE_CONSOLE
// Allocate a texture coordinate, returning its ID to be used with glMultiTexCoord.
@ -159,6 +157,7 @@ public:
private:
void AddSlice(ShaderSliceList& slices, int iPos, const char *szText, const char *szSource, int iFileTime);
void AddSlices(ShaderSliceList& slices, const char *szWhat, const char *szText, const char *szSource, int iFileTime);
bool LoadSlices(ShaderSliceList& slices, C4GroupSet *pGroupSet, const char *szFile);
int ParsePosition(const char *szWhat, const char **ppPos);
StdStrBuf Build(const ShaderSliceList &Slices, bool fDebug = false);

View File

@ -554,8 +554,9 @@ const char *C4LandscapeRenderGL::UniformNames[C4LRU_Count+1];
bool C4LandscapeRenderGL::LoadShader(C4GroupSet *pGroups, C4Shader& shader, const char* name, int ssc)
{
// Create vertex shader (hard-coded)
shader.AddVertexDefaults();
// Create vertex shader
shader.LoadVertexSlices(pGroups, "LandscapeVertexShader.glsl");
hLandscapeTexCoord = shader.AddTexCoord("landscapeCoord");
if(ssc & C4SSC_LIGHT) hLightTexCoord = shader.AddTexCoord("lightCoord");
@ -564,8 +565,8 @@ bool C4LandscapeRenderGL::LoadShader(C4GroupSet *pGroups, C4Shader& shader, cons
shader.AddFragmentSlice(-1, "#define OC_LANDSCAPE");
if(ssc & C4SSC_LIGHT) shader.AddFragmentSlice(-1, "#define OC_DYNAMIC_LIGHT"); // sample light from light texture
shader.LoadSlices(pGroups, "CommonShader.glsl");
shader.LoadSlices(pGroups, "LandscapeShader.glsl");
shader.LoadFragmentSlices(pGroups, "CommonShader.glsl");
shader.LoadFragmentSlices(pGroups, "LandscapeShader.glsl");
// Initialise!
if (!shader.Init(name, UniformNames)) {
@ -590,6 +591,7 @@ bool C4LandscapeRenderGL::LoadShaders(C4GroupSet *pGroups)
// Make uniform name map
ZeroMem(UniformNames, sizeof(UniformNames));
UniformNames[C4LRU_ProjectionMatrix] = "projectionMatrix";
UniformNames[C4LRU_LandscapeTex] = "landscapeTex";
UniformNames[C4LRU_ScalerTex] = "scalerTex";
UniformNames[C4LRU_MaterialTex] = "materialTex";
@ -905,6 +907,7 @@ void C4LandscapeRenderGL::Draw(const C4TargetFacet &cgo, const C4FoWRegion *Ligh
ShaderCall.Start();
// Bind data
ShaderCall.SetUniformMatrix4x4(C4LRU_ProjectionMatrix, pGL->GetProjectionMatrix());
ShaderCall.SetUniform3fv(C4LRU_Gamma, 1, pGL->gammaOut);
ShaderCall.SetUniform2f(C4LRU_Resolution, Surfaces[0]->Wdt, Surfaces[0]->Hgt);
float centerX = float(cgo.TargetX)+float(cgo.Wdt)/2,

View File

@ -36,6 +36,8 @@ enum C4LR_Byte {
// Don't forget to update GetUniformName when introducing new uniforms!
enum C4LR_Uniforms
{
C4LRU_ProjectionMatrix,
C4LRU_LandscapeTex,
C4LRU_ScalerTex,
C4LRU_MaterialTex,

View File

@ -30,21 +30,20 @@ C4Shader *C4FoW::GetFramebufShader()
// Not created yet?
if (!FramebufShader.Initialised())
{
// Create the frame buffer shader. The details are in C4FoWRegion, but
// this is about how to utilise old frame buffer data in the lights texture.
// Or put in other words: This shader is responsible for fading lights out.
FramebufShader.AddVertexDefaults();
FramebufShader.AddVertexSlice(-1, "uniform mat4 projectionMatrix;");
FramebufShader.AddVertexSlice(0, "gl_Position = projectionMatrix * gl_Vertex;");
FramebufShader.AddTexCoord("texCoord");
FramebufShader.AddFragmentSlice(-1, "uniform sampler2D tex;");
FramebufShader.AddFragmentSlice(0,
"gl_FragColor = texture2D(tex, texCoord.st);");
const char *szUniforms[] = { "tex", NULL };
const char *szUniforms[] = { "tex", "projectionMatrix", NULL };
if (!FramebufShader.Init("framebuf", szUniforms)) {
FramebufShader.ClearSlices();
return NULL;
}
}
return &FramebufShader;
#else
@ -52,6 +51,31 @@ C4Shader *C4FoW::GetFramebufShader()
#endif
}
C4Shader *C4FoW::GetRenderShader()
{
#ifndef USE_CONSOLE
// Not created yet?
if (!RenderShader.Initialised())
{
// Create the render shader. Fairly simple pass-through.
RenderShader.AddVertexSlice(-1, "uniform mat4 projectionMatrix;");
RenderShader.AddVertexSlice(0, "gl_FrontColor = gl_Color; gl_Position = projectionMatrix * gl_Vertex;");
RenderShader.AddFragmentSlice(0,
"gl_FragColor = gl_Color;");
const char *szUniforms[] = { "projectionMatrix", NULL };
if (!RenderShader.Init("fowRender", szUniforms)) {
RenderShader.ClearSlices();
return NULL;
}
}
return &RenderShader;
#else
return NULL;
#endif
}
void C4FoW::Add(C4Object *pObj)
{
#ifndef USE_CONSOLE
@ -119,11 +143,22 @@ void C4FoW::Update(C4Rect r, C4Player *pPlr)
#endif
}
void C4FoW::Render(C4FoWRegion *pRegion, const C4TargetFacet *pOnScreen, C4Player *pPlr)
void C4FoW::Render(C4FoWRegion *pRegion, const C4TargetFacet *pOnScreen, C4Player *pPlr, const StdProjectionMatrix& projectionMatrix)
{
#ifndef USE_CONSOLE
// Set up shader. If this one doesn't work, we're really in trouble.
C4Shader *pShader = GetRenderShader();
assert(pShader);
if (!pShader) return;
C4ShaderCall Call(pShader);
Call.Start();
Call.SetUniformMatrix4x4(0, projectionMatrix);
for (C4FoWLight *pLight = pLights; pLight; pLight = pLight->getNext())
if (pLight->IsVisibleForPlayer(pPlr))
pLight->Render(pRegion, pOnScreen);
Call.Finish();
#endif
}

View File

@ -83,6 +83,8 @@ public:
// Shader to use for updating the frame buffer
C4Shader *GetFramebufShader();
// Shader to use for rendering the lights
C4Shader *GetRenderShader();
void Clear();
@ -96,12 +98,13 @@ public:
/** Triggers the recalculation of all light beams within the given rectangle because the landscape changed. */
void Invalidate(C4Rect r);
void Render(class C4FoWRegion *pRegion, const C4TargetFacet *pOnScreen, C4Player *pPlr);
void Render(class C4FoWRegion *pRegion, const C4TargetFacet *pOnScreen, C4Player *pPlr, const StdProjectionMatrix& projectionMatrix);
private:
#ifndef USE_CONSOLE
// Shader for updating the frame buffer
C4Shader FramebufShader;
C4Shader RenderShader;
#endif
};

View File

@ -15,6 +15,7 @@
#include "C4Include.h"
#include "C4FoWRegion.h"
#include "C4DrawGL.h"
C4FoWRegion::~C4FoWRegion()
{
@ -121,7 +122,7 @@ void C4FoWRegion::Render(const C4TargetFacet *pOnScreen)
// On screen? No need to set up frame buffer - simply shortcut
if (pOnScreen)
{
pFoW->Render(this, pOnScreen, pPlayer);
pFoW->Render(this, pOnScreen, pPlayer, pGL->GetProjectionMatrix());
return;
}
@ -143,10 +144,7 @@ void C4FoWRegion::Render(const C4TargetFacet *pOnScreen)
// Set up a clean context
glViewport(0, 0, pSurface->Wdt, pSurface->Hgt);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, pSurface->Wdt, pSurface->Hgt, 0);
const StdProjectionMatrix projectionMatrix = StdProjectionMatrix::Orthographic(0.0, pSurface->Wdt, pSurface->Hgt, 0);
// Clear texture contents
assert(pSurface->Hgt % 2 == 0);
@ -163,7 +161,7 @@ void C4FoWRegion::Render(const C4TargetFacet *pOnScreen)
// Render FoW to frame buffer object
glBlendFunc(GL_ONE, GL_ONE);
pFoW->Render(this, NULL, pPlayer);
pFoW->Render(this, NULL, pPlayer, projectionMatrix);
// Copy over the old state
if (OldRegion.Wdt > 0)
@ -198,6 +196,7 @@ void C4FoWRegion::Render(const C4TargetFacet *pOnScreen)
Call.Start();
if (Call.AllocTexUnit(0))
glBindTexture(GL_TEXTURE_2D, pBackSurface->textures[0].texName);
Call.SetUniformMatrix4x4(1, projectionMatrix);
glBlendFunc(GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_COLOR);
float normalBlend = 1.0f / 4.0f, // Normals change quickly
brightBlend = 1.0f / 16.0f; // Intensity more slowly
@ -214,8 +213,6 @@ void C4FoWRegion::Render(const C4TargetFacet *pOnScreen)
// Done!
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
pDraw->RestorePrimaryClipper();
OldRegion = Region;

View File

@ -414,6 +414,28 @@ StdProjectionMatrix StdProjectionMatrix::Rotate(float angle, float rx, float ry,
return m;
}
StdProjectionMatrix StdProjectionMatrix::Orthographic(float left, float right, float bottom, float top)
{
StdProjectionMatrix matrix;
matrix(0,0) = 2.0f / (right - left);
matrix(0,1) = 0.0f;
matrix(0,2) = 0.0f;
matrix(0,3) = -(right + left) / (right - left);
matrix(1,0) = 0.0f;
matrix(1,1) = 2.0f / (top - bottom);
matrix(1,2) = 0.0f;
matrix(1,3) = -(top + bottom) / (top - bottom);
matrix(2,0) = 0.0f;
matrix(2,1) = 0.0f;
matrix(2,2) = -1.0f;
matrix(2,3) = 0.0f;
matrix(3,0) = 0.0f;
matrix(3,1) = 0.0f;
matrix(3,2) = 0.0f;
matrix(3,3) = 1.0f;
return matrix;
}
StdMeshMatrix StdProjectionMatrix::Upper3x4(const StdProjectionMatrix& matrix)
{
StdMeshMatrix m;

View File

@ -126,6 +126,9 @@ public:
static StdProjectionMatrix Translate(float dx, float dy, float dz);
static StdProjectionMatrix Scale(float sx, float sy, float sz);
static StdProjectionMatrix Rotate(float angle, float rx, float ry, float rz);
static StdProjectionMatrix Orthographic(float left, float right, float bottom, float top);
static StdMeshMatrix Upper3x4(const StdProjectionMatrix& matrix);
float& operator()(int i, int j) { return a[i][j]; }

View File

@ -71,8 +71,8 @@ public:
if (ssc & C4SSC_BASE) shader.AddFragmentSlice(-1, "#define OC_HAVE_BASE");
if (ssc & C4SSC_OVERLAY) shader.AddFragmentSlice(-1, "#define OC_HAVE_OVERLAY");
shader.LoadSlices(&::GraphicsResource.Files, "CommonShader.glsl");
shader.LoadSlices(&::GraphicsResource.Files, "ObjectShader.glsl");
shader.LoadFragmentSlices(&::GraphicsResource.Files, "CommonShader.glsl");
shader.LoadFragmentSlices(&::GraphicsResource.Files, "ObjectShader.glsl");
#endif
}