terraintexenvcombine.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 385 行
CPP
385 行
/*
---------------------------------------------------------------------
Terrain Renderer using texture splatting and geomipmapping
Copyright (c) 2006 Jelmer Cnossen
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
Jelmer Cnossen
j.cnossen at gmail dot com
---------------------------------------------------------------------
*/
#include "StdAfx.h"
#include "TerrainBase.h"
#include "TerrainTexture.h"
#include "TerrainTexEnvCombine.h"
namespace terrain {
using namespace std;
uint NodeTexEnvSetup::GetVertexDataRequirements ()
{
return VRT_Normal;
}
string NodeTexEnvSetup::GetDebugDesc ()
{
string str;
const char *opstr[] = {
"Replace",
"Mul",
"Add",
"AddSigned",
"Sub",
"Previous",
"Interp", // interpolate: color = prev.RGB * prev.Alpha + current.RGB * ( 1-prev.Alpha )
"InsertAlpha", // same as previous, but does not allow color invert
"Dot3" // dot product, requires GL_ARB_texture_env_dot3
};
const char *srcstr[] = {
"None", "TextureSrc", "ColorSrc"
};
for (int a=0;a<stages.size();a++)
{
str += "{" + string(opstr[(int)stages[a].operation]) + ", " + srcstr[(int)stages[a].source];
if (stages[a].source == TexEnvStage::TextureSrc) str += " = " + string(stages[a].srcTexture->name);
str += "} ";
};
return str;
}
void NodeTexEnvSetup::GetTextureUnits(BaseTexture *tex, int& imageUnit,int& coordUnit)
{
for (int a=0;a<stages.size();a++)
if (stages[a].source == TexEnvStage::TextureSrc && stages[a].srcTexture == tex) {
imageUnit = coordUnit = a;
break;
}
}
//-----------------------------------------------------------------------
// texture env state builder
//-----------------------------------------------------------------------
TexEnvStage::TexEnvStage ()
{
operation = Replace;
srcTexture = 0;
source=None;
}
TexEnvSetupHandler::TexEnvSetupHandler()
{
hasDot3 = !!GLEW_ARB_texture_env_dot3;
// Create white texture
glGenTextures (1, &whiteTexture);
glBindTexture (GL_TEXTURE_2D, whiteTexture);
uint pixel=0xffffffff;
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, 1,1,0,GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
curSetup=0;
lastShader=0;
maxtu = 0;
}
int TexEnvSetupHandler::MaxTextureUnits ()
{
int m;
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &m);
return m;
}
int TexEnvSetupHandler::MaxTextureCoords ()
{
int m;
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &m);
return m;
}
void TexEnvSetupHandler::BuildNodeSetup (ShaderDef* shaderDef, RenderSetup* renderSetup)
{
int maxTextureUnits = MaxTextureUnits();
unsigned int c = 0;
NodeTexEnvSetup *setup = curSetup = SAFE_NEW NodeTexEnvSetup;
renderSetup->passes.push_back(RenderPass());
renderSetup->passes.back().shaderSetup = setup;
renderSetup->passes.back().depthWrite = true;
// Handle the first stages with texture units
while (c < maxTextureUnits && c < shaderDef->stages.size())
{
ShaderDef::Stage& st = shaderDef->stages[c];
if(st.operation == ShaderDef::Alpha && c==maxTextureUnits-1) // blending needs 2 stages
break;
setup->stages.push_back (TexEnvStage());
TexEnvStage& ts = setup->stages.back();
ts.source = TexEnvStage::TextureSrc;
ts.srcTexture = st.source;
switch (st.operation) {
case ShaderDef::Blend:
ts.operation = TexEnvStage::Interp;
break;
case ShaderDef::Alpha:
ts.operation = TexEnvStage::InsertAlpha;
break;
case ShaderDef::Add:
ts.operation = TexEnvStage::Add;
break;
case ShaderDef::Mul:
ts.operation = TexEnvStage::Mul;
break;
}
if (!c)
ts.operation = TexEnvStage::Replace;
c++;
}
// Switch to multipass when the stages couldn't all be handled with multitexturing
while (c < shaderDef->stages.size())
{
ShaderDef::Stage& st = shaderDef->stages[c];
renderSetup->passes.push_back(RenderPass());
RenderPass& rp = renderSetup->passes.back();
rp.shaderSetup = setup = SAFE_NEW NodeTexEnvSetup;
if (st.operation == ShaderDef::Alpha) {
assert (shaderDef->stages[c+1].operation == ShaderDef::Blend);
setup->stages.push_back (TexEnvStage());
TexEnvStage& interp = setup->stages.back();
interp.operation = TexEnvStage::Replace;
interp.source = TexEnvStage::TextureSrc;
interp.srcTexture = shaderDef->stages[c+1].source;
setup->stages.push_back (TexEnvStage());
TexEnvStage& a = setup->stages.back();
a.operation = TexEnvStage::InsertAlpha;
a.source = TexEnvStage::TextureSrc;
a.srcTexture = st.source;
c++; // skip the blend stage because we used it here already
rp.operation = Pass_Interpolate;
}
else if (st.operation == ShaderDef::Add || st.operation == ShaderDef::Mul)
{
setup->stages.push_back (TexEnvStage());
TexEnvStage& ts = setup->stages.back();
ts.operation = TexEnvStage::Replace;
ts.source = TexEnvStage::TextureSrc;
ts.srcTexture = st.source;
if (st.operation == ShaderDef::Add)
rp.operation = Pass_Add;
else
rp.operation = Pass_Mul;
}
c++;
}
if (!shaderDef->hasLighting)
{
// multiply with color: this is either done through an extra texture stage, or with another pass
if (c < maxTextureUnits)
{
// extra stage
setup->stages.push_back (TexEnvStage());
TexEnvStage& ts = setup->stages.back();
ts.source = TexEnvStage::ColorSrc;
ts.operation = TexEnvStage::Mul;
}
else
{
// extra pass
renderSetup->passes.push_back(RenderPass());
renderSetup->passes.back().operation = Pass_Mul;
renderSetup->passes.back().shaderSetup = setup = SAFE_NEW NodeTexEnvSetup;
setup->stages.push_back (TexEnvStage());
setup->stages.back().source = TexEnvStage::ColorSrc;
setup->stages.back().operation = TexEnvStage::Replace;
}
}
}
void TexEnvSetupHandler::BeginPass (const vector<Blendmap*>& blendMaps, const vector<TiledTexture*>& textures, int pass)
{}
bool TexEnvSetupHandler::SetupShader (IShaderSetup *shadercfg, NodeSetupParams& parms)
{
NodeTexEnvSetup* ns = (NodeTexEnvSetup *)shadercfg;
int tu = 0;// texture unit
for (int cur = 0; cur < ns->stages.size(); cur ++)
{
TexEnvStage& st = ns->stages[cur];
glActiveTextureARB(GL_TEXTURE0_ARB + tu);
glEnable (GL_TEXTURE_2D);
glTexEnvf (GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
glTexEnvf (GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0f);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
// default alpha operation
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_CONSTANT_ARB);
float envcolor[]={1.0f,1.0f,1.0f,1.0f};
glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envcolor);
// Set source
glDisable(GL_LIGHTING);
BaseTexture *texture = 0;
switch (st.source) {
case TexEnvStage::ColorSrc:
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
glEnable (GL_LIGHTING);
break;
case TexEnvStage::TextureSrc:
texture = st.srcTexture;
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
break;
}
if (texture) {
float v[4];
texture->CalcTexGenVector (v);
SetTexCoordGen (v);
if (texture->id) glBindTexture (GL_TEXTURE_2D, texture->id);
} else
glBindTexture (GL_TEXTURE_2D, whiteTexture);
// set operation
switch (st.operation) {
case TexEnvStage::Mul:
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
break;
case TexEnvStage::Add:
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD);
break;
case TexEnvStage::Sub:
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_SUBTRACT_ARB);
break;
case TexEnvStage::Replace:
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
break;
case TexEnvStage::InsertAlpha:
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
break;
case TexEnvStage::Interp: // color=tex * previous.alpha + tex * previous.alpha
// Use previous alpha
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
break;
case TexEnvStage::Dot3:
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGB_ARB);
break;
case TexEnvStage::AlphaToRGB:
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_ALPHA);
break;
}
tu++;
}
ns->usedTexUnits = tu;
if (maxtu<tu) maxtu = tu;
// Disable texture units of the last node
if (lastShader) {
for (int u = ns->usedTexUnits; u < lastShader->usedTexUnits; u++) {
glActiveTextureARB (GL_TEXTURE0_ARB + u);
glDisable (GL_TEXTURE_2D);
}
}
lastShader = ns;
return true;
}
void TexEnvSetupHandler::BeginTexturing()
{
lastShader = 0;
maxtu = 0;
}
void TexEnvSetupHandler::EndTexturing ()
{
for (int a=0;a<maxtu;a++) {
glActiveTextureARB(GL_TEXTURE0_ARB+a);
glDisable (GL_TEXTURE_2D);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
glDisable (GL_TEXTURE_GEN_S);
glDisable (GL_TEXTURE_GEN_T);
}
maxtu=0;
glActiveTextureARB(GL_TEXTURE0_ARB);
glDisable (GL_LIGHTING);
}
void TexEnvSetupHandler::SetTexCoordGen (float *tgv)
{
glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
Plane s(tgv[0],0,0,tgv[2]);
glTexGenfv (GL_S, GL_OBJECT_PLANE, (float*)&s);
Plane t(0,0,tgv[1],tgv[3]);
glTexGenfv (GL_T, GL_OBJECT_PLANE, (float*)&t);
glEnable (GL_TEXTURE_GEN_S);
glEnable (GL_TEXTURE_GEN_T);
}
};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?