# Support separate rotation and scaling for each terrain texture

This was SVN commit r10952.
This commit is contained in:
Ykkrosh 2012-01-22 18:20:33 +00:00
parent 2b96eafdb4
commit 7f679a7975
14 changed files with 169 additions and 65 deletions

Binary file not shown.

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Terrains>
<Terrain angle="0.0" size="4.0"/>
</Terrains>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Textures>
<File pattern="grid_subdiv.png" format="rgba"/>
</Textures>

View File

@ -3,8 +3,9 @@
<vertex file="terrain_common.vp">
<uniform name="sunColor" loc="0" type="vec3"/>
<uniform name="losTransform" loc="1" type="vec2"/>
<uniform name="shadowTransform" loc="2" type="mat4"/>
<uniform name="textureTransform" loc="1" type="vec4"/>
<uniform name="losTransform" loc="2" type="vec2"/>
<uniform name="shadowTransform" loc="3" type="mat4"/>
</vertex>
<fragment file="terrain_common.fp">

View File

@ -5,8 +5,9 @@
<vertex file="terrain_common.vp">
<uniform name="sunColor" loc="0" type="vec3"/>
<uniform name="losTransform" loc="1" type="vec2"/>
<uniform name="shadowTransform" loc="2" type="mat4"/>
<uniform name="textureTransform" loc="1" type="vec4"/>
<uniform name="losTransform" loc="2" type="vec2"/>
<uniform name="shadowTransform" loc="3" type="mat4"/>
</vertex>
<fragment file="terrain_common.fp">

View File

@ -1,7 +1,8 @@
!!ARBvp1.0
PARAM sunColor = program.local[0];
PARAM losTransform = program.local[1];
PARAM shadowTransform[4] = { program.local[2..5] };
PARAM textureTransform = program.local[1];
PARAM losTransform = program.local[2];
PARAM shadowTransform[4] = { program.local[3..6] };
TEMP lighting;
@ -24,7 +25,17 @@ MUL result.color, lighting, sunColor;
//// Texture coordinates:
MOV result.texcoord[0], vertex.texcoord[0];
#ifdef DECAL
MOV result.texcoord[0], vertex.texcoord[0];
#else
// Compute texcoords from position and terrain-texture-dependent transform.
// textureTransform is stored as [c, -s, s, 0],
// and we want texcoord = (x*c + z*-s, x*-s + z*-c, 0, 1)
DP3 result.texcoord[0].x, textureTransform.xyww, position.xzww;
DP3 result.texcoord[0].y, -textureTransform.zxww, position.xzww;
MOV result.texcoord[0].z, 0;
MOV result.texcoord[0].w, 1;
#endif
#ifdef BLEND
MOV result.texcoord[1], vertex.texcoord[1];

View File

@ -5,8 +5,9 @@
<vertex file="terrain_common.vp">
<uniform name="sunColor" loc="0" type="vec3"/>
<uniform name="losTransform" loc="1" type="vec2"/>
<uniform name="shadowTransform" loc="2" type="mat4"/>
<uniform name="textureTransform" loc="1" type="vec4"/>
<uniform name="losTransform" loc="2" type="vec2"/>
<uniform name="shadowTransform" loc="3" type="mat4"/>
</vertex>
<fragment file="terrain_common.fp">

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010 Wildfire Games.
/* Copyright (C) 2012 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -31,11 +31,14 @@
#include "TerrainTextureManager.h"
#include "ps/Overlay.h"
#include "maths/MathUtil.h"
CTerrainProperties::CTerrainProperties(CTerrainPropertiesPtr parent):
m_pParent(parent),
m_BaseColor(0),
m_HasBaseColor(false),
m_TextureAngle((float)M_PI / 4.f),
m_TextureSize(32.f),
m_MovementClass("default")
{
if (m_pParent)
@ -98,6 +101,8 @@ void CTerrainProperties::LoadXml(XMBElement node, CXeromyces *pFile, const VfsPa
ATTR(mmap);
ATTR(groups);
ATTR(movementclass);
ATTR(angle);
ATTR(size);
#undef ELMT
#undef ATTR
@ -137,6 +142,14 @@ void CTerrainProperties::LoadXml(XMBElement node, CXeromyces *pFile, const VfsPa
baseColor[3] = (u8)(col.a*255);
m_HasBaseColor = true;
}
else if (attr.Name == attr_angle)
{
m_TextureAngle = DEGTORAD(attr.Value.ToFloat());
}
else if (attr.Name == attr_size)
{
m_TextureSize = attr.Value.ToFloat();
}
else if (attr.Name == attr_movementclass)
{
m_MovementClass = attr.Value;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010 Wildfire Games.
/* Copyright (C) 2012 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -56,6 +56,12 @@ private:
CStr m_MovementClass;
// Orientation of texture (in radians) (default pi/4 = 45 degrees)
float m_TextureAngle;
// Size of texture in metres (default 32m = 8 tiles)
float m_TextureSize;
// All terrain type groups we're a member of
GroupVector m_Groups;
@ -86,6 +92,16 @@ public:
// The color value is in BGRA format
u32 GetBaseColor();
float GetTextureAngle()
{
return m_TextureAngle;
}
float GetTextureSize()
{
return m_TextureSize;
}
CStr GetMovementClass() const
{
return m_MovementClass;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010 Wildfire Games.
/* Copyright (C) 2012 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -17,18 +17,20 @@
#include "precompiled.h"
#include <map>
#include "TerrainTextureEntry.h"
#include "lib/utf8.h"
#include "lib/ogl.h"
#include "lib/res/graphics/ogl_tex.h"
#include "TerrainTextureEntry.h"
#include "TerrainTextureManager.h"
#include "TerrainProperties.h"
#include "Texture.h"
#include "graphics/Terrain.h"
#include "graphics/TerrainTextureManager.h"
#include "graphics/TerrainProperties.h"
#include "graphics/Texture.h"
#include "renderer/Renderer.h"
#include <map>
CTerrainTextureEntry::CTerrainTextureEntry(CTerrainPropertiesPtr props, const VfsPath& path):
m_pProperties(props),
m_BaseColor(0),
@ -47,9 +49,23 @@ CTerrainTextureEntry::CTerrainTextureEntry(CTerrainPropertiesPtr props, const Vf
if (CRenderer::IsInitialised())
m_Texture = g_Renderer.GetTextureManager().CreateTexture(texture);
float texAngle = 0.f;
float texSize = 1.f;
if (m_pProperties)
{
m_Groups = m_pProperties->GetGroups();
texAngle = m_pProperties->GetTextureAngle();
texSize = m_pProperties->GetTextureSize();
}
m_TextureMatrix.SetZero();
m_TextureMatrix._11 = cosf(texAngle) / texSize;
m_TextureMatrix._13 = -sinf(texAngle) / texSize;
m_TextureMatrix._21 = -sinf(texAngle) / texSize;
m_TextureMatrix._23 = -cosf(texAngle) / texSize;
m_TextureMatrix._44 = 1.f;
GroupVector::iterator it=m_Groups.begin();
for (;it!=m_Groups.end();++it)
(*it)->AddTerrain(this);
@ -82,3 +98,8 @@ void CTerrainTextureEntry::BuildBaseColor()
m_BaseColorValid = true;
}
}
const float* CTerrainTextureEntry::GetTextureMatrix()
{
return &m_TextureMatrix._11;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010 Wildfire Games.
/* Copyright (C) 2012 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -25,6 +25,7 @@
#include "lib/res/handle.h"
#include "lib/file/vfs/vfs_path.h"
#include "maths/Matrix3D.h"
#include "ps/CStr.h"
class XMBElement;
@ -46,6 +47,8 @@ private:
CTerrainPropertiesPtr m_pProperties;
CTexturePtr m_Texture;
CMatrix3D m_TextureMatrix;
// BGRA color of topmost mipmap level, for coloring minimap, or a color
// specified by the terrain properties
@ -75,17 +78,16 @@ public:
const CTexturePtr& GetTexture() {
return m_Texture;
}
// Returns a matrix of the form [c 0 -s 0; -s 0 -c 0; 0 0 0 0; 0 0 0 1]
// mapping world-space (x,y,z,1) coordinates onto (u,v,0,1) texcoords
const float* GetTextureMatrix();
// Get mipmap color in BGRA format
u32 GetBaseColor() {
if (!m_BaseColorValid) BuildBaseColor();
return m_BaseColor;
}
// ScEd wants to sort textures by their group's index.
size_t GetType() const
{ return m_Groups[0]->GetIndex(); }
const GroupVector &GetGroups() const
{ return m_Groups; }
};
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2011 Wildfire Games.
/* Copyright (C) 2012 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -80,14 +80,6 @@ CPatchRData::~CPatchRData()
if (m_VBWaterIndices) g_VBMan.Release(m_VBWaterIndices);
}
const float uvFactor = 0.125f / sqrt(2.f);
static void CalculateUV(float uv[2], ssize_t x, ssize_t z)
{
// The UV axes are offset 45 degrees from XZ
uv[0] = ( x-z)*uvFactor;
uv[1] = (-x-z)*uvFactor;
}
/**
* Represents a blend for a single tile, texture and shape.
*/
@ -373,7 +365,6 @@ void CPatchRData::AddBlend(std::vector<SBlendVertex>& blendVertices, std::vector
size_t index = blendVertices.size();
CalculateUV(dst.m_UVs, gx, gz);
terrain->CalcPosition(gx, gz, dst.m_Position);
terrain->CalcNormal(gx, gz, normal);
dst.m_DiffuseColor = lightEnv.EvaluateDiffuse(normal, includeSunColor);
@ -381,7 +372,6 @@ void CPatchRData::AddBlend(std::vector<SBlendVertex>& blendVertices, std::vector
dst.m_AlphaUVs[1] = vtx[0].m_AlphaUVs[1];
blendVertices.push_back(dst);
CalculateUV(dst.m_UVs, gx + 1, gz);
terrain->CalcPosition(gx + 1, gz, dst.m_Position);
terrain->CalcNormal(gx + 1, gz, normal);
dst.m_DiffuseColor = lightEnv.EvaluateDiffuse(normal, includeSunColor);
@ -389,7 +379,6 @@ void CPatchRData::AddBlend(std::vector<SBlendVertex>& blendVertices, std::vector
dst.m_AlphaUVs[1] = vtx[1].m_AlphaUVs[1];
blendVertices.push_back(dst);
CalculateUV(dst.m_UVs, gx + 1, gz + 1);
terrain->CalcPosition(gx + 1, gz + 1, dst.m_Position);
terrain->CalcNormal(gx + 1, gz + 1, normal);
dst.m_DiffuseColor = lightEnv.EvaluateDiffuse(normal, includeSunColor);
@ -397,7 +386,6 @@ void CPatchRData::AddBlend(std::vector<SBlendVertex>& blendVertices, std::vector
dst.m_AlphaUVs[1] = vtx[2].m_AlphaUVs[1];
blendVertices.push_back(dst);
CalculateUV(dst.m_UVs, gx, gz + 1);
terrain->CalcPosition(gx, gz + 1, dst.m_Position);
terrain->CalcNormal(gx, gz + 1, normal);
dst.m_DiffuseColor = lightEnv.EvaluateDiffuse(normal, includeSunColor);
@ -552,7 +540,6 @@ void CPatchRData::BuildVertices()
// calculate vertex data
terrain->CalcPosition(ix,iz,vertices[v].m_Position);
CalculateUV(vertices[v].m_UVs, ix, iz);
// Calculate diffuse lighting for this vertex
// Ambient is added by the lighting pass (since ambient is the same
@ -721,7 +708,7 @@ typedef POOLED_BATCH_MAP(CVertexBuffer*, IndexBufferBatches) VertexBufferBatches
// Group batches by texture
typedef POOLED_BATCH_MAP(CTerrainTextureEntry*, VertexBufferBatches) TextureBatches;
void CPatchRData::RenderBases(const std::vector<CPatchRData*>& patches)
void CPatchRData::RenderBases(const std::vector<CPatchRData*>& patches, CShaderProgramPtr shader)
{
Allocators::Arena<> arena(ARENA_SIZE);
@ -758,9 +745,26 @@ void CPatchRData::RenderBases(const std::vector<CPatchRData*>& patches)
for (TextureBatches::iterator itt = batches.begin(); itt != batches.end(); ++itt)
{
if (itt->first)
{
itt->first->GetTexture()->Bind();
if (shader)
{
float c = itt->first->GetTextureMatrix()[0];
float ms = itt->first->GetTextureMatrix()[8];
shader->Uniform("textureTransform", c, ms, -ms, 0.f);
}
else
{
glMatrixMode(GL_TEXTURE);
glLoadMatrixf(itt->first->GetTextureMatrix());
glMatrixMode(GL_MODELVIEW);
}
}
else
{
g_Renderer.GetTextureManager().GetErrorTexture()->Bind();
}
for (VertexBufferBatches::iterator itv = itt->second.begin(); itv != itt->second.end(); ++itv)
{
@ -768,7 +772,7 @@ void CPatchRData::RenderBases(const std::vector<CPatchRData*>& patches)
SBaseVertex *base = (SBaseVertex *)itv->first->Bind();
glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]);
glColorPointer(4, GL_UNSIGNED_BYTE, stride, &base->m_DiffuseColor);
glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs[0]);
glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position[0]);
for (IndexBufferBatches::iterator it = itv->second.begin(); it != itv->second.end(); ++it)
{
@ -791,6 +795,13 @@ void CPatchRData::RenderBases(const std::vector<CPatchRData*>& patches)
}
}
if (!shader)
{
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
CVertexBuffer::Unbind();
}
@ -825,7 +836,7 @@ struct SBlendStackItem
SplatStack splats;
};
void CPatchRData::RenderBlends(const std::vector<CPatchRData*>& patches)
void CPatchRData::RenderBlends(const std::vector<CPatchRData*>& patches, CShaderProgramPtr shader)
{
Allocators::Arena<> arena(ARENA_SIZE);
@ -913,9 +924,27 @@ void CPatchRData::RenderBlends(const std::vector<CPatchRData*>& patches)
for (BatchesStack::iterator itt = batches.begin(); itt != batches.end(); ++itt)
{
if (itt->m_Texture)
{
itt->m_Texture->GetTexture()->Bind();
if (shader)
{
float c = itt->m_Texture->GetTextureMatrix()[0];
float ms = itt->m_Texture->GetTextureMatrix()[8];
shader->Uniform("textureTransform", c, ms, -ms, 0.f);
}
else
{
pglClientActiveTextureARB(GL_TEXTURE0);
glMatrixMode(GL_TEXTURE);
glLoadMatrixf(itt->m_Texture->GetTextureMatrix());
glMatrixMode(GL_MODELVIEW);
}
}
else
{
g_Renderer.GetTextureManager().GetErrorTexture()->Bind();
}
for (VertexBufferBatches::iterator itv = itt->m_Batches.begin(); itv != itt->m_Batches.end(); ++itv)
{
@ -931,7 +960,7 @@ void CPatchRData::RenderBlends(const std::vector<CPatchRData*>& patches)
glColorPointer(4, GL_UNSIGNED_BYTE, stride, &base->m_DiffuseColor);
pglClientActiveTextureARB(GL_TEXTURE0);
glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs[0]);
glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position[0]);
pglClientActiveTextureARB(GL_TEXTURE1);
glTexCoordPointer(2, GL_FLOAT, stride, &base->m_AlphaUVs[0]);
@ -958,6 +987,13 @@ void CPatchRData::RenderBlends(const std::vector<CPatchRData*>& patches)
pglClientActiveTextureARB(GL_TEXTURE0);
if (!shader)
{
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
CVertexBuffer::Unbind();
}
@ -990,6 +1026,8 @@ void CPatchRData::RenderStreams(const std::vector<CPatchRData*>& patches, int st
PROFILE_END("compute batches");
ENSURE(!(streamflags & ~(STREAM_POS|STREAM_COLOR|STREAM_POSTOUV1)));
// Render each batch
for (VertexBufferBatches::iterator itv = batches.begin(); itv != batches.end(); ++itv)
{
@ -997,11 +1035,6 @@ void CPatchRData::RenderStreams(const std::vector<CPatchRData*>& patches, int st
SBaseVertex *base = (SBaseVertex *)itv->first->Bind();
glVertexPointer(3, GL_FLOAT, stride, &base->m_Position);
if (streamflags & STREAM_UV0)
{
pglClientActiveTextureARB(GL_TEXTURE0);
glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs);
}
if (streamflags & STREAM_POSTOUV0)
{
pglClientActiveTextureARB(GL_TEXTURE0);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2011 Wildfire Games.
/* Copyright (C) 2012 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -22,6 +22,7 @@
#include "graphics/SColor.h"
#include "maths/Vector3D.h"
#include "graphics/RenderableObject.h"
#include "graphics/ShaderProgram.h"
#include "VertexBufferManager.h"
class CPatch;
@ -43,8 +44,8 @@ public:
void RenderWater();
static void RenderBases(const std::vector<CPatchRData*>& patches);
static void RenderBlends(const std::vector<CPatchRData*>& patches);
static void RenderBases(const std::vector<CPatchRData*>& patches, CShaderProgramPtr shader);
static void RenderBlends(const std::vector<CPatchRData*>& patches, CShaderProgramPtr shader);
static void RenderStreams(const std::vector<CPatchRData*>& patches, int streamflags);
CPatch* GetPatch() { return m_Patch; }
@ -70,12 +71,8 @@ private:
CVector3D m_Position;
// diffuse color from sunlight
SColor4ub m_DiffuseColor;
// vertex uvs for base texture
float m_UVs[2];
// add some padding since VBOs prefer power-of-two sizes
u32 m_Padding[2];
};
cassert(sizeof(SBaseVertex) == 32);
cassert(sizeof(SBaseVertex) == 16);
struct SSideVertex {
// vertex position
@ -90,10 +87,10 @@ private:
CVector3D m_Position;
// diffuse color from sunlight
SColor4ub m_DiffuseColor;
// vertex uvs for base texture
float m_UVs[2];
// vertex uvs for alpha texture
float m_AlphaUVs[2];
// add some padding since VBOs prefer power-of-two sizes
u32 m_Padding[2];
};
cassert(sizeof(SBlendVertex) == 32);

View File

@ -227,7 +227,7 @@ void TerrainRenderer::RenderTerrain(bool filtered)
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, one);
PROFILE_START("render terrain base");
CPatchRData::RenderBases(visiblePatches);
CPatchRData::RenderBases(visiblePatches, CShaderProgramPtr());
PROFILE_END("render terrain base");
// render blends
@ -260,7 +260,7 @@ void TerrainRenderer::RenderTerrain(bool filtered)
// render blend passes for each patch
PROFILE_START("render terrain blends");
CPatchRData::RenderBlends(visiblePatches);
CPatchRData::RenderBlends(visiblePatches, CShaderProgramPtr());
PROFILE_END("render terrain blends");
// Disable second texcoord array
@ -402,10 +402,6 @@ void TerrainRenderer::PrepareShader(const CShaderProgramPtr& shader, ShadowMap*
shader->BindTexture("losTex", los.GetTexture());
shader->Uniform("losTransform", los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f);
CTerritoryTexture& territory = g_Renderer.GetScene().GetTerritoryTexture();
shader->BindTexture("territoryTex", territory.GetTexture());
shader->Uniform("territoryTransform", territory.GetTextureMatrix()[0], territory.GetTextureMatrix()[12], 0.f, 0.f);
shader->Uniform("ambient", lightEnv.m_TerrainAmbientColor);
shader->Uniform("sunColor", lightEnv.m_SunColor);
}
@ -455,7 +451,7 @@ void TerrainRenderer::RenderTerrainShader(ShadowMap* shadow, bool filtered)
PrepareShader(shaderBase, shadow);
PROFILE_START("render terrain base");
CPatchRData::RenderBases(visiblePatches);
CPatchRData::RenderBases(visiblePatches, shaderBase);
PROFILE_END("render terrain base");
shaderBase->Unbind();
@ -481,7 +477,7 @@ void TerrainRenderer::RenderTerrainShader(ShadowMap* shadow, bool filtered)
// render blend passes for each patch
PROFILE_START("render terrain blends");
CPatchRData::RenderBlends(visiblePatches);
CPatchRData::RenderBlends(visiblePatches, shaderBlend);
PROFILE_END("render terrain blends");
// Disable second texcoord array