forked from Mirrors/openclonk
Avoid built-in GL matrices for sprite rendering
Instead, compute the projection, modelview and normal matrices explictly and upload them as shader uniforms. This is one step towards using the OpenGL 3 core profile.shapetextures
parent
609840fda0
commit
a9967e7b16
|
@ -2,6 +2,7 @@
|
|||
uniform mat3x2 lightTransform;
|
||||
|
||||
#ifdef OC_WITH_NORMALMAP
|
||||
uniform mat3 normalMatrix;
|
||||
uniform sampler2D normalTex;
|
||||
#endif
|
||||
|
||||
|
@ -69,7 +70,13 @@ slice(normal)
|
|||
#ifdef OC_WITH_NORMALMAP
|
||||
vec4 normalPx = texture2D(normalTex, texcoord.xy);
|
||||
vec3 normalPxDir = 2.0 * (normalPx.xyz - vec3(0.5, 0.5, 0.5));
|
||||
#ifdef OC_MESH
|
||||
// TODO: Change to normalMatrix once we changed mesh rendering
|
||||
// to use custom matrices
|
||||
vec3 normal = normalize(gl_NormalMatrix * normalPxDir);
|
||||
#else
|
||||
vec3 normal = normalize(normalMatrix * normalPxDir);
|
||||
#endif
|
||||
#else
|
||||
#ifdef OC_MESH
|
||||
vec3 normal = normalDir; // Normal matrix is already applied in vertex shader
|
||||
|
|
|
@ -173,9 +173,39 @@ bool CStdGL::UpdateClipper()
|
|||
glLoadIdentity();
|
||||
|
||||
gluOrtho2D((GLdouble) clipRect.x, (GLdouble) (clipRect.x + clipRect.Wdt), (GLdouble) (clipRect.y + clipRect.Hgt), (GLdouble) clipRect.y);
|
||||
UpdateProjectionMatrix();
|
||||
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 near = -1.0f;
|
||||
const float far = +1.0f;
|
||||
|
||||
ProjectionMatrix[0] = 2.0f / (right - left);
|
||||
ProjectionMatrix[1] = 0.0f;
|
||||
ProjectionMatrix[2] = 0.0f;
|
||||
ProjectionMatrix[3] = -(right + left) / (right - left);
|
||||
ProjectionMatrix[4] = 0.0f;
|
||||
ProjectionMatrix[5] = 2.0f / (top - bottom);
|
||||
ProjectionMatrix[6] = 0.0f;
|
||||
ProjectionMatrix[7] = -(top + bottom) / (top - bottom);
|
||||
ProjectionMatrix[8] = 0.0f;
|
||||
ProjectionMatrix[9] = 0.0f;
|
||||
ProjectionMatrix[10] = -2.0f / (far - near);
|
||||
ProjectionMatrix[11] = -(far + near) / (far - near);
|
||||
ProjectionMatrix[12] = 0.0f;
|
||||
ProjectionMatrix[13] = 0.0f;
|
||||
ProjectionMatrix[14] = 0.0f;
|
||||
ProjectionMatrix[15] = 1.0f;
|
||||
}
|
||||
|
||||
bool CStdGL::PrepareRendering(C4Surface * sfcToSurface)
|
||||
{
|
||||
// call from gfx thread only!
|
||||
|
@ -207,11 +237,18 @@ bool CStdGL::PrepareRendering(C4Surface * sfcToSurface)
|
|||
|
||||
bool CStdGL::PrepareSpriteShader(C4Shader& shader, const char* name, int ssc, C4GroupSet* pGroups, const char* const* additionalDefines, const char* const* additionalSlices)
|
||||
{
|
||||
static const char vertexUniforms[] =
|
||||
"uniform mat4 projectionMatrix;"
|
||||
"uniform mat4 modelviewMatrix;";
|
||||
|
||||
static const char vertexSlice[] =
|
||||
" gl_FrontColor = gl_Color;"
|
||||
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;";
|
||||
" gl_Position = projectionMatrix * modelviewMatrix * gl_Vertex;";
|
||||
|
||||
const char* uniformNames[C4SSU_Count + 1];
|
||||
uniformNames[C4SSU_ProjectionMatrix] = "projectionMatrix";
|
||||
uniformNames[C4SSU_ModelViewMatrix] = "modelviewMatrix";
|
||||
uniformNames[C4SSU_NormalMatrix] = "normalMatrix";
|
||||
uniformNames[C4SSU_ClrMod] = "clrMod";
|
||||
uniformNames[C4SSU_Gamma] = "gamma";
|
||||
uniformNames[C4SSU_BaseTex] = "baseTex";
|
||||
|
@ -223,14 +260,15 @@ bool CStdGL::PrepareSpriteShader(C4Shader& shader, const char* name, int ssc, C4
|
|||
uniformNames[C4SSU_AmbientTex] = "ambientTex";
|
||||
uniformNames[C4SSU_AmbientTransform] = "ambientTransform";
|
||||
uniformNames[C4SSU_AmbientBrightness] = "ambientBrightness";
|
||||
uniformNames[C4SSU_Bones] = "bones";
|
||||
uniformNames[C4SSU_CullMode] = "cullMode";
|
||||
uniformNames[C4SSU_Bones] = "bones"; // unused
|
||||
uniformNames[C4SSU_CullMode] = "cullMode"; // unused
|
||||
uniformNames[C4SSU_Count] = NULL;
|
||||
|
||||
// Clear previous content
|
||||
shader.Clear();
|
||||
shader.ClearSlices();
|
||||
|
||||
shader.AddVertexSlice(-1, vertexUniforms);
|
||||
shader.AddVertexSlice(C4Shader_Vertex_PositionPos, vertexSlice);
|
||||
|
||||
// Add texture coordinate if we have base texture, overlay, or normal map
|
||||
|
@ -384,7 +422,7 @@ bool CStdGL::CreatePrimarySurfaces(unsigned int, unsigned int, int iColorDepth,
|
|||
return ok;
|
||||
}
|
||||
|
||||
void CStdGL::SetupMultiBlt(C4ShaderCall& call, const C4BltTransform* pTransform, GLuint baseTex, GLuint overlayTex, GLuint normalTex, DWORD dwOverlayModClr)
|
||||
void CStdGL::SetupMultiBlt(C4ShaderCall& call, const C4BltTransform* pTransform, GLuint baseTex, GLuint overlayTex, GLuint normalTex, DWORD dwOverlayModClr, StdMeshMatrix* out_modelview)
|
||||
{
|
||||
// Initialize multi blit shader.
|
||||
int iAdditive = dwBlitMode & C4GFXBLIT_ADDITIVE;
|
||||
|
@ -457,36 +495,57 @@ void CStdGL::SetupMultiBlt(C4ShaderCall& call, const C4BltTransform* pTransform,
|
|||
|
||||
call.SetUniform1f(C4SSU_CullMode, 0.0f);
|
||||
|
||||
StdMeshMatrix default_modelview = StdMeshMatrix::Identity();
|
||||
StdMeshMatrix& modelview = out_modelview ? *out_modelview : default_modelview;
|
||||
|
||||
// Apply zoom and transform
|
||||
glPushMatrix();
|
||||
glTranslatef(ZoomX, ZoomY, 0.0f);
|
||||
Translate(modelview, ZoomX, ZoomY, 0.0f);
|
||||
// Scale Z as well so that we don't distort normals.
|
||||
glScalef(Zoom, Zoom, Zoom);
|
||||
glTranslatef(-ZoomX, -ZoomY, 0.0f);
|
||||
Scale(modelview, Zoom, Zoom, Zoom);
|
||||
Translate(modelview, -ZoomX, -ZoomY, 0.0f);
|
||||
|
||||
if(pTransform)
|
||||
{
|
||||
// Decompose scale factors and scale Z accordingly to X and Y, again to avoid distorting normals
|
||||
// We could instead work around this by using the projection matrix, but then for object rotations (SetR)
|
||||
// the normals would not be correct.
|
||||
const float sx = sqrt(pTransform->mat[0]*pTransform->mat[0] + pTransform->mat[1]*pTransform->mat[1]);
|
||||
const float sy = sqrt(pTransform->mat[3]*pTransform->mat[3] + pTransform->mat[4]*pTransform->mat[4]);
|
||||
const float sz = sqrt(sx * sy);
|
||||
const GLfloat transform[16] = { pTransform->mat[0], pTransform->mat[3], 0, pTransform->mat[6], pTransform->mat[1], pTransform->mat[4], 0, pTransform->mat[7], 0, 0, sz, 0, pTransform->mat[2], pTransform->mat[5], 0, pTransform->mat[8] };
|
||||
glMultMatrixf(transform);
|
||||
}
|
||||
}
|
||||
float sz = 1.0f;
|
||||
if (pFoW != NULL && normalTex != 0)
|
||||
{
|
||||
// Decompose scale factors and scale Z accordingly to X and Y, again to avoid distorting normals
|
||||
// We could instead work around this by using the projection matrix, but then for object rotations (SetR)
|
||||
// the normals would not be correct.
|
||||
const float sx = sqrt(pTransform->mat[0]*pTransform->mat[0] + pTransform->mat[1]*pTransform->mat[1]);
|
||||
const float sy = sqrt(pTransform->mat[3]*pTransform->mat[3] + pTransform->mat[4]*pTransform->mat[4]);
|
||||
sz = sqrt(sx * sy);
|
||||
}
|
||||
|
||||
void CStdGL::ResetMultiBlt()
|
||||
{
|
||||
glPopMatrix();
|
||||
// Multiply modelview matrix with transform
|
||||
StdMeshMatrix transform;
|
||||
transform(0, 0) = pTransform->mat[0];
|
||||
transform(0, 1) = pTransform->mat[1];
|
||||
transform(0, 2) = 0.0f;
|
||||
transform(0, 3) = pTransform->mat[2];
|
||||
transform(1, 0) = pTransform->mat[3];
|
||||
transform(1, 1) = pTransform->mat[4];
|
||||
transform(1, 2) = 0.0f;
|
||||
transform(1, 3) = pTransform->mat[5];
|
||||
transform(2, 0) = pTransform->mat[6];
|
||||
transform(2, 1) = pTransform->mat[7];
|
||||
transform(2, 2) = sz;
|
||||
transform(2, 3) = pTransform->mat[8];
|
||||
|
||||
modelview *= transform;
|
||||
}
|
||||
|
||||
call.SetUniformMatrix4x4fv(C4SSU_ProjectionMatrix, 1, ProjectionMatrix);
|
||||
call.SetUniformMatrix4x4(C4SSU_ModelViewMatrix, modelview);
|
||||
|
||||
if (pFoW != NULL && normalTex != 0)
|
||||
call.SetUniformMatrix3x3Transpose(C4SSU_NormalMatrix, StdMeshMatrix::Inverse(modelview));
|
||||
}
|
||||
|
||||
void CStdGL::PerformMultiPix(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, C4ShaderCall* shader_call)
|
||||
{
|
||||
// Draw on pixel center:
|
||||
glPushMatrix();
|
||||
glTranslatef(0.5f, 0.5f, 0.0f);
|
||||
StdMeshMatrix transform = StdMeshMatrix::Translate(0.5f, 0.5f, 0.0f);
|
||||
|
||||
// This is a workaround. Instead of submitting the whole vertex array to the GL, we do it
|
||||
// in batches of 256 vertices. The intel graphics driver on Linux crashes with
|
||||
|
@ -498,20 +557,16 @@ void CStdGL::PerformMultiPix(C4Surface* sfcTarget, const C4BltVertex* vertices,
|
|||
if (!shader_call)
|
||||
{
|
||||
C4ShaderCall call(GetSpriteShader(false, false, false));
|
||||
SetupMultiBlt(call, NULL, 0, 0, 0, 0);
|
||||
SetupMultiBlt(call, NULL, 0, 0, 0, 0, &transform);
|
||||
for(unsigned int i = 0; i < n_vertices; i += BATCH_SIZE)
|
||||
PerformMultiBlt(sfcTarget, OP_POINTS, &vertices[i], std::min(n_vertices - i, BATCH_SIZE), false);
|
||||
ResetMultiBlt();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupMultiBlt(*shader_call, NULL, 0, 0, 0, 0);
|
||||
SetupMultiBlt(*shader_call, NULL, 0, 0, 0, 0, &transform);
|
||||
for(unsigned int i = 0; i < n_vertices; i += BATCH_SIZE)
|
||||
PerformMultiBlt(sfcTarget, OP_POINTS, &vertices[i], std::min(n_vertices - i, BATCH_SIZE), false);
|
||||
ResetMultiBlt();
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void CStdGL::PerformMultiLines(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, float width, C4ShaderCall* shader_call)
|
||||
|
@ -562,15 +617,13 @@ void CStdGL::PerformMultiLines(C4Surface* sfcTarget, const C4BltVertex* vertices
|
|||
if (!shader_call)
|
||||
{
|
||||
C4ShaderCall call(GetSpriteShader(true, false, false));
|
||||
SetupMultiBlt(call, NULL, lines_tex, 0, 0, 0);
|
||||
SetupMultiBlt(call, NULL, lines_tex, 0, 0, 0, NULL);
|
||||
PerformMultiBlt(sfcTarget, OP_TRIANGLES, tri_vertices, n_vertices * 3, true);
|
||||
ResetMultiBlt();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupMultiBlt(*shader_call, NULL, lines_tex, 0, 0, 0);
|
||||
SetupMultiBlt(*shader_call, NULL, lines_tex, 0, 0, 0, NULL);
|
||||
PerformMultiBlt(sfcTarget, OP_TRIANGLES, tri_vertices, n_vertices * 3, true);
|
||||
ResetMultiBlt();
|
||||
}
|
||||
|
||||
delete[] tri_vertices;
|
||||
|
@ -582,15 +635,13 @@ void CStdGL::PerformMultiTris(C4Surface* sfcTarget, const C4BltVertex* vertices,
|
|||
if (!shader_call)
|
||||
{
|
||||
C4ShaderCall call(GetSpriteShader(pTex != NULL, pOverlay != NULL, pNormal != NULL));
|
||||
SetupMultiBlt(call, pTransform, pTex ? pTex->texName : 0, pOverlay ? pOverlay->texName : 0, pNormal ? pNormal->texName : 0, dwOverlayModClr);
|
||||
SetupMultiBlt(call, pTransform, pTex ? pTex->texName : 0, pOverlay ? pOverlay->texName : 0, pNormal ? pNormal->texName : 0, dwOverlayModClr, NULL);
|
||||
PerformMultiBlt(sfcTarget, OP_TRIANGLES, vertices, n_vertices, pTex != NULL);
|
||||
ResetMultiBlt();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupMultiBlt(*shader_call, pTransform, pTex ? pTex->texName : 0, pOverlay ? pOverlay->texName : 0, pNormal ? pNormal->texName : 0, dwOverlayModClr);
|
||||
SetupMultiBlt(*shader_call, pTransform, pTex ? pTex->texName : 0, pOverlay ? pOverlay->texName : 0, pNormal ? pNormal->texName : 0, dwOverlayModClr, NULL);
|
||||
PerformMultiBlt(sfcTarget, OP_TRIANGLES, vertices, n_vertices, pTex != NULL);
|
||||
ResetMultiBlt();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,10 @@ private:
|
|||
// Uniform data we give the sprite shader (constants from its viewpoint)
|
||||
enum C4SS_Uniforms
|
||||
{
|
||||
C4SSU_ProjectionMatrix, // 4x4
|
||||
C4SSU_ModelViewMatrix, // 4x4
|
||||
C4SSU_NormalMatrix, // 3x3, transpose-inverse of modelview matrix
|
||||
|
||||
C4SSU_ClrMod, // always
|
||||
C4SSU_Gamma, // always
|
||||
|
||||
|
@ -129,6 +133,10 @@ protected:
|
|||
int iClrDpt; // color depth
|
||||
// texture for smooth lines
|
||||
GLuint lines_tex;
|
||||
|
||||
// The orthographic projection matrix
|
||||
float ProjectionMatrix[16];
|
||||
|
||||
// programs for drawing points, lines, quads
|
||||
|
||||
// Sprite shaders -- there is a variety of shaders to avoid
|
||||
|
@ -159,6 +167,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();
|
||||
virtual bool PrepareMaterial(StdMeshMatManager& mat_manager, StdMeshMaterialLoader& loader, StdMeshMaterial& mat);
|
||||
// Surface
|
||||
virtual bool PrepareRendering(C4Surface * sfcToSurface); // check if/make rendering possible to given surface
|
||||
|
@ -169,8 +178,7 @@ public:
|
|||
virtual CStdGLCtx *CreateContext(HWND hWindow, C4AbstractApp *pApp);
|
||||
#endif
|
||||
// Blit
|
||||
void SetupMultiBlt(C4ShaderCall& call, const C4BltTransform* pTransform, GLuint baseTex, GLuint overlayTex, GLuint normalTex, DWORD dwOverlayModClr);
|
||||
void ResetMultiBlt();
|
||||
void SetupMultiBlt(C4ShaderCall& call, const C4BltTransform* pTransform, GLuint baseTex, GLuint overlayTex, GLuint normalTex, DWORD dwOverlayModClr, StdMeshMatrix* out_modelview);
|
||||
virtual void PerformMesh(StdMeshInstance &instance, float tx, float ty, float twdt, float thgt, DWORD dwPlayerColor, C4BltTransform* pTransform);
|
||||
void FillBG(DWORD dwClr=0);
|
||||
// Drawing
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define INC_C4Shader
|
||||
|
||||
#include "StdBuf.h"
|
||||
#include "StdMeshMath.h"
|
||||
#include "C4Surface.h"
|
||||
|
||||
// Shader version
|
||||
|
@ -230,6 +231,11 @@ public:
|
|||
glUniformMatrix3x2fv(pShader->GetUniform(iUniform), iLength, GL_TRUE, pVals);
|
||||
}
|
||||
|
||||
void SetUniformMatrix3x3fv(int iUniform, int iLength, const float *pVals) const {
|
||||
if (pShader->HaveUniform(iUniform))
|
||||
glUniformMatrix3fv(pShader->GetUniform(iUniform), iLength, GL_TRUE, pVals);
|
||||
}
|
||||
|
||||
void SetUniformMatrix3x4fv(int iUniform, int iLength, const float *pVals) const {
|
||||
if (pShader->HaveUniform(iUniform))
|
||||
glUniformMatrix4x3fv(pShader->GetUniform(iUniform), iLength, GL_TRUE, pVals);
|
||||
|
@ -240,6 +246,39 @@ public:
|
|||
glUniformMatrix4fvARB(pShader->GetUniform(iUniform), iLength, GL_TRUE, pVals);
|
||||
}
|
||||
|
||||
void SetUniformMatrix3x3(int iUniform, const StdMeshMatrix& matrix)
|
||||
{
|
||||
if (pShader->HaveUniform(iUniform))
|
||||
{
|
||||
const float mat[9] = { matrix(0, 0), matrix(1, 0), matrix(2, 0), matrix(0, 1), matrix(1, 1), matrix(2, 1), matrix(0, 2), matrix(1, 2), matrix(2, 2) };
|
||||
glUniformMatrix3fv(pShader->GetUniform(iUniform), 1, GL_FALSE, mat);
|
||||
}
|
||||
}
|
||||
|
||||
void SetUniformMatrix3x3Transpose(int iUniform, const StdMeshMatrix& matrix)
|
||||
{
|
||||
if (pShader->HaveUniform(iUniform))
|
||||
{
|
||||
const float mat[9] = { matrix(0, 0), matrix(0, 1), matrix(0, 2), matrix(1, 0), matrix(1, 1), matrix(1, 2), matrix(2, 0), matrix(2, 1), matrix(2, 2) };
|
||||
glUniformMatrix3fv(pShader->GetUniform(iUniform), 1, GL_FALSE, mat);
|
||||
}
|
||||
}
|
||||
|
||||
void SetUniformMatrix3x4(int iUniform, const StdMeshMatrix& matrix)
|
||||
{
|
||||
if (pShader->HaveUniform(iUniform))
|
||||
glUniformMatrix4x3fv(pShader->GetUniform(iUniform), 1, GL_TRUE, matrix.data());
|
||||
}
|
||||
|
||||
void SetUniformMatrix4x4(int iUniform, const StdMeshMatrix& matrix)
|
||||
{
|
||||
if (pShader->HaveUniform(iUniform))
|
||||
{
|
||||
const float mat[16] = { matrix(0, 0), matrix(1, 0), matrix(2, 0), 0.0f, matrix(0, 1), matrix(1, 1), matrix(1, 2), 0.0f, matrix(2, 0), matrix(2, 1), matrix(2, 2), 0.0f, matrix(0, 3), matrix(1, 3), matrix(2, 3), 1.0f };
|
||||
glUniformMatrix4fvARB(pShader->GetUniform(iUniform), 1, GL_FALSE, mat);
|
||||
}
|
||||
}
|
||||
|
||||
void Start();
|
||||
void Finish();
|
||||
};
|
||||
|
|
|
@ -978,7 +978,7 @@ bool C4ParticleChunk::Exec(C4Object *obj, float timeDelta)
|
|||
#define glDeleteVertexArrays glDeleteVertexArraysAPPLE
|
||||
#endif
|
||||
|
||||
void C4ParticleChunk::Draw(C4TargetFacet cgo, C4Object *obj, int texUnit)
|
||||
void C4ParticleChunk::Draw(C4TargetFacet cgo, C4Object *obj, C4ShaderCall& call, int texUnit, const StdMeshMatrix& modelview)
|
||||
{
|
||||
if (particleCount == 0) return;
|
||||
const int stride = sizeof(C4Particle::DrawingData::Vertex);
|
||||
|
@ -987,12 +987,16 @@ void C4ParticleChunk::Draw(C4TargetFacet cgo, C4Object *obj, int texUnit)
|
|||
assert(textureRef != 0 && "Particle definition had no texture assigned.");
|
||||
|
||||
// use a relative offset?
|
||||
bool resetMatrix(false);
|
||||
// (note the normal matrix is unaffected by this)
|
||||
if ((attachment & C4ATTACH_MoveRelative) && (obj != 0))
|
||||
{
|
||||
resetMatrix = true;
|
||||
glPushMatrix();
|
||||
glTranslatef((float)obj->GetX(), (float)obj->GetY(), 0.0f);
|
||||
StdMeshMatrix new_modelview(modelview);
|
||||
Translate(new_modelview, fixtof(obj->GetFixedX()), fixtof(obj->GetFixedY()), 0.0f);
|
||||
call.SetUniformMatrix4x4(C4SSU_ModelViewMatrix, new_modelview);
|
||||
}
|
||||
else
|
||||
{
|
||||
call.SetUniformMatrix4x4(C4SSU_ModelViewMatrix, modelview);
|
||||
}
|
||||
|
||||
// enable additive blending for particles with that blit mode
|
||||
|
@ -1063,8 +1067,6 @@ void C4ParticleChunk::Draw(C4TargetFacet cgo, C4Object *obj, int texUnit)
|
|||
{
|
||||
glMultiDrawElements(GL_TRIANGLE_STRIP, ::Particles.GetMultiDrawElementsCountArray(), GL_UNSIGNED_INT, const_cast<const GLvoid**>(::Particles.GetMultiDrawElementsIndexArray()), static_cast<GLsizei> (particleCount));
|
||||
}
|
||||
if (resetMatrix)
|
||||
glPopMatrix();
|
||||
|
||||
// reset buffer data
|
||||
if (!Particles.useBufferObjectWorkaround)
|
||||
|
@ -1158,9 +1160,11 @@ void C4ParticleList::Draw(C4TargetFacet cgo, C4Object *obj)
|
|||
// enable shader
|
||||
C4ShaderCall call(pGL->GetSpriteShader(true, false, false));
|
||||
// apply zoom and upload shader uniforms
|
||||
pGL->SetupMultiBlt(call, NULL, 0, 0, 0, 0);
|
||||
// go to correct output position
|
||||
glTranslatef(cgo.X-cgo.TargetX, cgo.Y-cgo.TargetY, 0.0f);
|
||||
StdMeshMatrix modelview = StdMeshMatrix::Identity();
|
||||
pGL->SetupMultiBlt(call, NULL, 0, 0, 0, 0, &modelview);
|
||||
// go to correct output position (note the normal matrix is unaffected
|
||||
// by this)
|
||||
Translate(modelview, cgo.X-cgo.TargetX, cgo.Y-cgo.TargetY, 0.0f);
|
||||
// allocate texture unit for particle texture, and remember allocated
|
||||
// texture unit. Will be used for each particle chunk to bind
|
||||
// their texture to this unit.
|
||||
|
@ -1188,15 +1192,13 @@ void C4ParticleList::Draw(C4TargetFacet cgo, C4Object *obj)
|
|||
}
|
||||
else
|
||||
{
|
||||
(*iter)->Draw(cgo, obj, texUnit);
|
||||
(*iter)->Draw(cgo, obj, call, texUnit, modelview);
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
accessMutex.Leave();
|
||||
|
||||
pGL->ResetMultiBlt();
|
||||
|
||||
if (Particles.useBufferObjectWorkaround)
|
||||
{
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
|
|
@ -364,7 +364,7 @@ public:
|
|||
// removes all particles
|
||||
void Clear();
|
||||
bool Exec(C4Object *obj, float timeDelta);
|
||||
void Draw(C4TargetFacet cgo, C4Object *obj, int texUnit);
|
||||
void Draw(C4TargetFacet cgo, C4Object *obj, C4ShaderCall& call, int texUnit, const StdMeshMatrix& modelview);
|
||||
bool IsOfType(C4ParticleDef *def, uint32_t _blitMode, uint32_t attachment) const;
|
||||
bool IsEmpty() const { return !particleCount; }
|
||||
|
||||
|
|
|
@ -864,6 +864,9 @@ bool StdMeshMaterialProgram::CompileShader(StdMeshMaterialLoader& loader, C4Shad
|
|||
std::vector<const char*> uniformNames;
|
||||
#ifndef USE_CONSOLE
|
||||
uniformNames.resize(C4SSU_Count + ParameterNames.size() + 1);
|
||||
uniformNames[C4SSU_ProjectionMatrix] = "projectionMatrix"; // unused YET
|
||||
uniformNames[C4SSU_ModelViewMatrix] = "modelviewMatrix"; // unused YET
|
||||
uniformNames[C4SSU_NormalMatrix] = "normalMatrix"; // unused YET
|
||||
uniformNames[C4SSU_ClrMod] = "clrMod";
|
||||
uniformNames[C4SSU_Gamma] = "gamma";
|
||||
uniformNames[C4SSU_BaseTex] = "baseTex"; // unused
|
||||
|
|
|
@ -669,3 +669,23 @@ StdMeshVertex operator*(const StdMeshMatrix& lhs, const StdMeshVertex& rhs)
|
|||
vtx.u = rhs.u; vtx.v = rhs.v;
|
||||
return vtx;
|
||||
}
|
||||
|
||||
void Translate(StdMeshMatrix& mat, float dx, float dy, float dz)
|
||||
{
|
||||
mat(0, 3) += mat(0,0)*dx + mat(0,1)*dy + mat(0,2)*dz;
|
||||
mat(1, 3) += mat(1,0)*dx + mat(1,1)*dy + mat(1,2)*dz;
|
||||
mat(2, 3) += mat(2,0)*dx + mat(2,1)*dy + mat(2,2)*dz;
|
||||
}
|
||||
|
||||
void Scale(StdMeshMatrix& mat, float sx, float sy, float sz)
|
||||
{
|
||||
mat(0, 0) *= sx;
|
||||
mat(1, 0) *= sx;
|
||||
mat(2, 0) *= sx;
|
||||
mat(0, 1) *= sy;
|
||||
mat(1, 1) *= sy;
|
||||
mat(2, 1) *= sy;
|
||||
mat(0, 2) *= sz;
|
||||
mat(1, 2) *= sz;
|
||||
mat(2, 2) *= sz;
|
||||
}
|
||||
|
|
|
@ -102,6 +102,8 @@ public:
|
|||
float Determinant() const;
|
||||
StdMeshTransformation Decompose() const;
|
||||
|
||||
const float* data() const { return &a[0][0]; }
|
||||
|
||||
private:
|
||||
// 3x3 orthogonal + translation in last column
|
||||
float a[3][4];
|
||||
|
@ -142,4 +144,9 @@ StdMeshVertex operator*(float lhs, const StdMeshVertex& rhs);
|
|||
StdMeshVertex operator*(const StdMeshVertex& lhs, float rhs);
|
||||
StdMeshVertex operator*(const StdMeshMatrix& lhs, const StdMeshVertex& rhs);
|
||||
|
||||
// Multiply in-place the given matrix with a translation matrix to the right
|
||||
void Translate(StdMeshMatrix& mat, float dx, float dy, float dz);
|
||||
// Multiply in-place the given matrix with a scale matrix to the right
|
||||
void Scale(StdMeshMatrix& mat, float sx, float sy, float sz);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue