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 + -
显示快捷键?