terraintextureglsl.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 915 行 · 第 1/2 页
CPP
915 行
gentxt += "return Light(diffuse, color);}\n";
break;
case SM_DiffuseBumpmapMP:
if (passIndex == 0)
gentxt += "return color; }\n";
else // passIndex=1
gentxt += "return Light(ReadDiffuseColor(), color);}\n";
break;
}
fragmentShader.texts.push_back (gentxt);
fragmentShader.Build(GL_FRAGMENT_SHADER_ARB);
ns->fragmentShader = fragmentShader.handle;
}
void ShaderBuilder::BuildVertexShader(NodeGLSLShader *ns, uint passIndex, ShaderDef *sd)
{
lastVertexShader = Shader();
Shader& vertexShader = lastVertexShader;
AddPPDefines(sd, vertexShader, passIndex);
// generate texture coords
std::string tcgen = "void CalculateTexCoords() {\n";
for (int a=0;a<ns->texCoordGen.size();a++)
{
char buf[160];
sprintf (buf, "gl_TexCoord[%d].st = vec2(dot(gl_Vertex, gl_ObjectPlaneS[%d]), dot(gl_Vertex,gl_ObjectPlaneT[%d]));\n", a, a, a);
tcgen += buf;
}
tcgen += "}\n";
vertexShader.texts.push_back (tcgen);
vertexShader.AddFile("shaders/terrainVertexShader.glsl");
vertexShader.Build(GL_VERTEX_SHADER_ARB);
d_trace("Vertex shader build succesfully.");
ns->vertexShader = vertexShader.handle;
}
bool ShaderBuilder::ProcessStage(vector<ShaderDef::Stage>& stages, uint &index, std::string& opstr)
{
ShaderDef::Stage& stage = stages[index];
BaseTexture *texture = stage.source;
TexReq hwmax;
hwmax.GetFromGL();
TextureUsage tmpUsage = texUsage;
int tu = tmpUsage.AddTextureRead (hwmax.units, texture);
int tc = tmpUsage.AddTextureCoordRead (hwmax.coords, texture);
assert (tu >= 0 && tc >= 0);
if (index == 0) { // replace
texUsage = tmpUsage;
opstr = "color = " + GenTextureRead(tu,tc) + ";\n";
}
else if(stage.operation == ShaderDef::Alpha) {
// next operation is blend (alpha is autoinserted before blend)
assert (index < stages.size()-1 && stages[index+1].operation == ShaderDef::Blend);
ShaderDef::Stage& blendStage = stages[index+1];
int blendTU = tmpUsage.AddTextureRead(hwmax.units, blendStage.source);
int blendTC = tmpUsage.AddTextureCoordRead(hwmax.coords, blendStage.source);
assert (blendTU >= 0 && blendTC >= 0);
index++;
texUsage = tmpUsage;
opstr += "curalpha = " + GenTextureRead(tu, tc) + ".a;\n";
opstr += "color = mix(color, " + GenTextureRead(blendTU, blendTC) + ", curalpha);\n";
}
else if (stage.operation == ShaderDef::Add) {
texUsage = tmpUsage;
opstr += "color += " + GenTextureRead(tu, tc) + ";\n";
} else if (stage.operation == ShaderDef::Mul) {
texUsage = tmpUsage;
opstr += "color *= " + GenTextureRead(tu, tc) + ";\n";
}
index++;
return true;
}
void ShaderBuilder::Build(ShaderDef* shaderDef)
{
texUsage = TextureUsage();
shadingMethod = CalculateShadingMethod(shaderDef);
switch (shadingMethod) {
case SM_DiffuseSP:{
string opstr;
for (uint stage = 0; stage < shaderDef->stages.size(); )
ProcessStage(shaderDef->stages, stage, opstr);
EndPass(shaderDef, opstr);
break;}
case SM_DiffuseBumpmapSP:{
string diffusecode, bumpmapcode;
for (uint stage = 0; stage < shaderDef->stages.size(); )
ProcessStage(shaderDef->stages, stage, diffusecode);
for (uint stage = 0; stage < shaderDef->normalMapStages.size(); )
ProcessStage(shaderDef->normalMapStages, stage, bumpmapcode);
EndPass(shaderDef, diffusecode + "vec4 diffuse = color;\n" + bumpmapcode);
break;}
case SM_DiffuseBumpmapMP:{
string diffusecode;
for (uint stage = 0; stage < shaderDef->stages.size(); )
ProcessStage(shaderDef->stages, stage, diffusecode);
NodeGLSLShader *diffusePass = EndPass(shaderDef, diffusecode, 0);
// multipass: let the diffuse pass render to the buffer
// at this point nodeShader=0 and texUsage is empty
if (!buffer) buffer = new BufferTexture;
diffusePass->renderBuffer = buffer;
// add texture read operation to second pass
texUsage.AddTextureRead(-1, buffer);
string bumpmapcode;
for (uint stage = 0; stage < shaderDef->normalMapStages.size(); )
ProcessStage(shaderDef->normalMapStages, stage, bumpmapcode);
EndPass(shaderDef, bumpmapcode, 1);
break;}
case SM_Impossible:
throw content_error("Map has too many layers for bumpmapping on this hardware");
}
}
NodeGLSLShader::NodeGLSLShader()
{
vertexShader = program = fragmentShader = 0;
vertBufReq = 0;
tsmAttrib = -1;
wsLightDirLocation = wsEyePosLocation = -1;
shadowMapLocation = -1;
shadowMatrixLocation = -1;
shadowParamsLocation = -1;
renderBuffer = 0;
}
NodeGLSLShader::~NodeGLSLShader()
{
if (program) {
glDetachObjectARB(program,vertexShader);
glDetachObjectARB(program,fragmentShader);
glDeleteObjectARB(program);
}
if (fragmentShader) glDeleteObjectARB(fragmentShader);
if (vertexShader) glDeleteObjectARB(vertexShader);
}
void NodeGLSLShader::BindTSM (Vector3* buf, uint vertexSize)
{
// according to the GL_ARB_vertex_shader spec:
// The VertexAttrib*ARB entry points defined earlier can also be used to
// load attributes declared as a 2x2, 3x3 or 4x4 matrix in a vertex shader.
// Each column of a matrix takes up one generic 4-component attribute slot
// out of the MAX_VERTEX_ATTRIBS_ARB available slots. Matrices are loaded
// into these slots in column major order. Matrix columns need to be loaded
// in increasing slot numbers.
if (tsmAttrib >= 0) {
for (int a=0;a<3;a++) {
glEnableVertexAttribArrayARB(tsmAttrib+a);
glVertexAttribPointerARB(tsmAttrib+a, 3, GL_FLOAT, 0, vertexSize, buf + a);
}
}
}
void NodeGLSLShader::UnbindTSM ()
{
if (tsmAttrib >= 0) {
for (int a=0;a<3;a++)
glDisableVertexAttribArrayARB(tsmAttrib+a);
}
}
void NodeGLSLShader::Setup (NodeSetupParams& params)
{/*
if (renderBuffer) { // use a offscreen rendering buffer
renderBuffer->framebuffer->select();
glViewport(0, 0, renderBuffer->width, renderBuffer->height);
}*/
glUseProgramObjectARB(program);
for (int a=0;a<texUnits.size();a++) {
glActiveTextureARB( GL_TEXTURE0_ARB+a);
GLenum target;
if (texUnits[a]->IsRect()) target = GL_TEXTURE_RECTANGLE_ARB;
else target = GL_TEXTURE_2D;
if (texUnits[a]->id) glBindTexture(target, texUnits[a]->id);
glEnable (target);
}
for (int a=0;a<texCoordGen.size();a++) {
glActiveTextureARB(GL_TEXTURE0_ARB+a);
texCoordGen[a]->SetupTexGen ();
}
glActiveTextureARB(GL_TEXTURE0_ARB);
if (wsLightDirLocation >= 0 && params.wsLightDir)
glUniform3fARB(wsLightDirLocation, params.wsLightDir->x, params.wsLightDir->y, params.wsLightDir->z);
if (wsEyePosLocation >= 0 && params.wsEyePos)
glUniform3fARB(wsEyePosLocation, params.wsEyePos->x, params.wsEyePos->y, params.wsEyePos->z);
if (params.shadowMapParams)
{
if (shadowMapLocation>=0) {
glUniform1i(shadowMapLocation, texUnits.size());
glActiveTextureARB(GL_TEXTURE0_ARB+texUnits.size());
glBindTexture(GL_TEXTURE_2D, params.shadowMapParams->shadowMap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
}
ShadowMapParams& smp = *params.shadowMapParams;
if (shadowMatrixLocation>=0) glUniformMatrix4fvARB(shadowMatrixLocation, 1, GL_TRUE, smp.shadowMatrix);
if (shadowParamsLocation>=0) glUniform4fARB(shadowParamsLocation, smp.f_a, smp.f_b, smp.mid[0], smp.mid[1]);
}
}
void NodeGLSLShader::Cleanup()
{
for (int a=0;a<texUnits.size();a++) {
glActiveTextureARB( GL_TEXTURE0_ARB+a);
glDisable(texUnits[a]->IsRect() ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D);
}
glActiveTextureARB(GL_TEXTURE0_ARB);
glUseProgramObjectARB(0);
}
std::string NodeGLSLShader::GetDebugDesc ()
{
return debugstr;
}
uint NodeGLSLShader::GetVertexDataRequirements ()
{
return vertBufReq;
}
void NodeGLSLShader::GetTextureUnits(BaseTexture* tex, int &imageUnit, int& coordUnit)
{
}
GLSLShaderHandler::GLSLShaderHandler()
{
curShader = 0;
scShader = 0;
buffer = 0;
}
GLSLShaderHandler::~GLSLShaderHandler()
{
delete buffer;
delete scShader;
}
void GLSLShaderHandler::EndTexturing ()
{
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
if (curShader) {
curShader->Cleanup();
curShader = 0;
}
}
void GLSLShaderHandler::BeginTexturing()
{
}
void GLSLShaderHandler::BeginPass(const std::vector<Blendmap*>& blendmaps, const std::vector<TiledTexture*>& textures, int pass)
{
if (buffer) {
if ((buffer->width != gu->viewSizeX) || (buffer->height != gu->viewSizeY)) {
delete buffer;
buffer = SAFE_NEW BufferTexture;
}
}
if (buffer)
{
if (pass == 0) {
buffer->framebuffer->select();
glViewport(0, 0, buffer->width, buffer->height);
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
}
else if (pass==1) {
buffer->framebuffer->deselect();
glViewport(gu->viewPosX, gu->viewPosY, gu->viewSizeX, gu->viewSizeY);
}
}
}
bool GLSLShaderHandler::SetupShader (IShaderSetup *ps, NodeSetupParams& params)
{
if (curShader) {
curShader->Cleanup();
curShader = 0;
}
GLSLBaseShader* bs=static_cast<GLSLBaseShader*>(ps);
bs->Setup(params);
curShader = bs;
return true;
}
void GLSLShaderHandler::EndBuild()
{
bool multipass = false;
for (int a=0;a<renderSetups.size();a++)
if (renderSetups[a]->passes.size()>1) {
multipass = true;
break;
}
if (!multipass)
return;
scShader = new SimpleCopyShader(buffer);
// make sure all rendersetups have 2 passes
for (int a=0;a<renderSetups.size();a++)
{
if (renderSetups[a]->passes.size()==2)
continue;
// add a simple pass to add
renderSetups[a]->passes.push_back (RenderPass());
RenderPass& pass = renderSetups[a]->passes.back();
pass.depthWrite = true;
pass.operation = Pass_Replace;
pass.shaderSetup = new SimpleCopyNodeShader(scShader);
}
}
void GLSLShaderHandler::BuildNodeSetup (ShaderDef *shaderDef, RenderSetup *renderSetup)
{
ShaderBuilder shaderBuilder (renderSetup);
shaderBuilder.buffer = buffer;
shaderBuilder.Build(shaderDef);
buffer = shaderBuilder.buffer;
renderSetups.push_back (renderSetup);
}
int GLSLShaderHandler::MaxTextureUnits ()
{
int n;
glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &n);
return n;
}
int GLSLShaderHandler::MaxTextureCoords ()
{
int n;
glGetIntegerv (GL_MAX_TEXTURE_COORDS_ARB, &n);
return n;
}
SimpleCopyShader::SimpleCopyShader(BufferTexture *buf)
{
Shader fs, vs;
if(buf->IsRect())
fs.texts.push_back("#define UseTextureRECT");
fs.AddFile("shaders/terrainSimpleCopyFS.glsl");
fs.Build(GL_FRAGMENT_SHADER_ARB);
vs.AddFile("shaders/terrainSimpleCopyVS.glsl");
vs.Build(GL_VERTEX_SHADER_ARB);
vertexShader = vs.handle;
fragmentShader = fs.handle;
program = glCreateProgramObjectARB();
glAttachObjectARB(program, vertexShader);
glAttachObjectARB(program, fragmentShader);
glLinkProgramARB(program);
int isLinked;
glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &isLinked);
if (!isLinked)
{
d_trace ("Failed to link shaders. Showing info log:\n");
ShowInfoLog (program);
throw std::runtime_error("Failed to link shaders");
}
GLint srcTex = glGetUniformLocationARB(program, "sourceTexture");
glUseProgramObjectARB(program);
glUniform1iARB(srcTex, 0);
if (!buf->IsRect()) {
GLint invScreenDim = glGetUniformLocationARB(program, "invScreenDim");
glUniform2fARB(invScreenDim, 1.0f/gu->viewSizeX, 1.0f/gu->viewSizeY);
}
glUseProgramObjectARB(0);
source = buf;
}
SimpleCopyShader::~SimpleCopyShader()
{
glDetachObjectARB(program,vertexShader);
glDetachObjectARB(program,fragmentShader);
glDeleteObjectARB(program);
glDeleteObjectARB(fragmentShader);
glDeleteObjectARB(vertexShader);
}
void SimpleCopyShader::Setup()
{
GLenum target;
if (source->IsRect()) target = GL_TEXTURE_RECTANGLE_ARB;
else target = GL_TEXTURE_2D;
glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(target, source->id);
glEnable (target);
glUseProgramObjectARB(program);
}
void SimpleCopyShader::Cleanup()
{
glActiveTextureARB(GL_TEXTURE0_ARB);
if (source->IsRect()) glDisable(GL_TEXTURE_RECTANGLE_ARB);
else glDisable(GL_TEXTURE_2D);
glUseProgramObjectARB(0);
}
};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?