Exemplo n.º 1
0
bool CGLCG::LoadShader(const TCHAR *shaderFile)
{
	CCGShader cgShader;
	TCHAR shaderPath[MAX_PATH];
	TCHAR tempPath[MAX_PATH];
	CGprofile vertexProfile, fragmentProfile;
	GLenum error;

	if(!fboFunctionsLoaded) {
		MessageBox(NULL, TEXT("Your OpenGL graphics driver does not support framebuffer objects.\nYou will not be able to use CG shaders in OpenGL mode."), TEXT("CG Error"),
			MB_OK|MB_ICONEXCLAMATION);
        return false;
    }

	vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
	fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);

	cgGLDisableProfile(vertexProfile);
	cgGLDisableProfile(fragmentProfile);

	ClearPasses();

	if (shaderFile == NULL || *shaderFile==TEXT('\0'))
		return true;

	lstrcpy(shaderPath, shaderFile);
    ReduceToPath(shaderPath);

	SetCurrentDirectory(shaderPath);
	if(!cgShader.LoadShader(_tToChar(shaderFile)))
		return false;

	cgGLSetOptimalOptions(vertexProfile);
	cgGLSetOptimalOptions(fragmentProfile);

	/* insert dummy pass that will contain the original texture
	*/
	shaderPasses.push_back(shaderPass());

	for(CCGShader::passVector::iterator it=cgShader.shaderPasses.begin();
			it!=cgShader.shaderPasses.end();it++) {
		shaderPass pass;

		pass.scaleParams = it->scaleParams;
		/* if this is the last pass (the only one that can have CG_SCALE_NONE)
		   and no filter has been set use the GUI setting
		*/
		if(pass.scaleParams.scaleTypeX==CG_SCALE_NONE && !it->filterSet) {
			pass.linearFilter = GUI.BilinearFilter;
		} else {
			pass.linearFilter = it->linearFilter;
		}

        pass.frameCounterMod = it->frameCounterMod;

        pass.floatFbo = it->floatFbo;

		// paths in the meta file can be relative
		_tfullpath(tempPath,_tFromChar(it->cgShaderFile),MAX_PATH);
		char *fileContents = ReadShaderFileContents(tempPath);
		if(!fileContents)
			return false;

        // individual shader might include files, these should be relative to shader
        ReduceToPath(tempPath);
        SetCurrentDirectory(tempPath);

		pass.cgVertexProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents,
						vertexProfile, "main_vertex", NULL);

		checkForCgError("Compiling vertex program");

		pass.cgFragmentProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents,
							fragmentProfile, "main_fragment", NULL);

		checkForCgError("Compiling fragment program");

        // set path back for next pass
        SetCurrentDirectory(shaderPath);

		delete [] fileContents;
		if(!pass.cgVertexProgram || !pass.cgFragmentProgram) {
			return false;
		}
		cgGLLoadProgram(pass.cgVertexProgram);
		cgGLLoadProgram(pass.cgFragmentProgram);

		/* generate framebuffer and texture for this pass and apply
		   default texture settings
		*/
		glGenFramebuffers(1,&pass.fbo);
		glGenTextures(1,&pass.tex);
		glBindTexture(GL_TEXTURE_2D,pass.tex);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

		shaderPasses.push_back(pass);
	}

	for(std::vector<CCGShader::lookupTexture>::iterator it=cgShader.lookupTextures.begin();it!=cgShader.lookupTextures.end();it++) {		
		lookupTexture tex;
		strcpy(tex.id,it->id);

		/* generate texture for the lut and apply specified filter setting
		*/
		glGenTextures(1,&tex.tex);
		glBindTexture(GL_TEXTURE_2D,tex.tex);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, it->linearfilter?GL_LINEAR:GL_NEAREST);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, it->linearfilter?GL_LINEAR:GL_NEAREST);

		_tfullpath(tempPath,_tFromChar(it->texturePath),MAX_PATH);

		// simple file extension png/tga decision
		int strLen = strlen(it->texturePath);
		if(strLen>4) {
			if(!strcasecmp(&it->texturePath[strLen-4],".png")) {
				int width, height;
				bool hasAlpha;
				GLubyte *texData;
				if(loadPngImage(tempPath,width,height,hasAlpha,&texData)) {
					glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
					glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width,
						height, 0, hasAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, texData);
					free(texData);
				}
			} else if(!strcasecmp(&it->texturePath[strLen-4],".tga")) {
				STGA stga;
				if(loadTGA(tempPath,stga)) {
					glPixelStorei(GL_UNPACK_ROW_LENGTH, stga.width);
					glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, stga.width,
						stga.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, stga.data);
				}
			}
		}
		lookupTextures.push_back(tex);
	}

	/* enable texture unit 1 for the lookup textures
	*/
	glClientActiveTexture(GL_TEXTURE1);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glTexCoordPointer(2,GL_FLOAT,0,lut_coords);
	glClientActiveTexture(GL_TEXTURE0);

	/* generate textures and set default values for the pref-filled PREV deque.
	*/
	for(int i=0;i<prevPasses.size();i++) {
		glGenTextures(1,&prevPasses[i].tex);
		glBindTexture(GL_TEXTURE_2D,prevPasses[i].tex);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,512,512,0,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,NULL);
		glBindTexture(GL_TEXTURE_2D,0);
		prevPasses[i].textureSize.x = prevPasses[i].textureSize.y = prevPasses[i].textureSize.x = prevPasses[i].textureSize.y = 0;
		memset(prevPasses[i].texCoords,0,sizeof(prevPasses[i].texCoords));
	}

	shaderLoaded = true;
	
	return true;
}
Exemplo n.º 2
0
bool CD3DCG::LoadShader(const TCHAR *shaderFile)
{
	CCGShader cgShader;
	TCHAR shaderPath[MAX_PATH];
	TCHAR tempPath[MAX_PATH];
	HRESULT hr;
	GLenum error;

	ClearPasses();

	if (shaderFile == NULL || *shaderFile==TEXT('\0'))
		return true;

	lstrcpy(shaderPath,shaderFile);
	for(int i=lstrlen(shaderPath); i>=0; i--){
		if(IS_SLASH(shaderPath[i])){
			shaderPath[i]=TEXT('\0');
			break;
		}
	}

	SetCurrentDirectory(shaderPath);
	if(!cgShader.LoadShader(_tToChar(shaderFile)))
		return false;

	CGprofile vertexProfile = cgD3D9GetLatestVertexProfile();
	CGprofile pixelProfile = cgD3D9GetLatestPixelProfile();

	const char** vertexOptions = cgD3D9GetOptimalOptions(vertexProfile);
	const char** pixelOptions = cgD3D9GetOptimalOptions(pixelProfile);

	shaderPasses.push_back(shaderPass());

	for(CCGShader::passVector::iterator it=cgShader.shaderPasses.begin();
			it!=cgShader.shaderPasses.end();it++) {
		shaderPass pass;

		pass.scaleParams = it->scaleParams;
		/* if this is the last pass (the only one that can have CG_SCALE_NONE)
		   and no filter has been set use the GUI setting
		*/
		if(pass.scaleParams.scaleTypeX==CG_SCALE_NONE && !it->filterSet) {
			pass.linearFilter = GUI.BilinearFilter;
		} else {
			pass.linearFilter = it->linearFilter;
		}

		// paths in the meta file can be relative
		_tfullpath(tempPath,_tFromChar(it->cgShaderFile),MAX_PATH);
		char *fileContents = ReadShaderFileContents(tempPath);
		if(!fileContents)
			return false;

		pass.cgVertexProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents,
						vertexProfile, "main_vertex", vertexOptions);

		checkForCgError("Compiling vertex program");

		pass.cgFragmentProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents,
						pixelProfile, "main_fragment", pixelOptions);

		checkForCgError("Compiling fragment program");

		delete [] fileContents;
		if(!pass.cgVertexProgram || !pass.cgFragmentProgram) {
			return false;
		}
		if(pass.cgVertexProgram) {
			hr = cgD3D9LoadProgram(pass.cgVertexProgram,false,0);
		}
		checkForCgError("Loading vertex program");
		if(pass.cgFragmentProgram) {
			hr = cgD3D9LoadProgram(pass.cgFragmentProgram,false,0);
		}
		checkForCgError("Loading fragment program");

		/* generate vertex buffer
		*/
		
		hr = pDevice->CreateVertexBuffer(sizeof(VERTEX)*4,D3DUSAGE_WRITEONLY,0,D3DPOOL_MANAGED,&pass.vertexBuffer,NULL);
		if(FAILED(hr)) {
			pass.vertexBuffer = NULL;
			DXTRACE_ERR_MSGBOX(TEXT("Error creating vertex buffer"), hr);
			return false;
		}

		/* set up vertex declarations for the pass,
		   this also creates the vertex declaration
		*/
		setupVertexDeclaration(pass);

		shaderPasses.push_back(pass);
	}

	for(std::vector<CCGShader::lookupTexture>::iterator it=cgShader.lookupTextures.begin();it!=cgShader.lookupTextures.end();it++) {		
		lookupTexture tex;
		strcpy(tex.id,it->id);
		tex.linearFilter = it->linearfilter;

		_tfullpath(tempPath,_tFromChar(it->texturePath),MAX_PATH);

		hr = D3DXCreateTextureFromFileEx(
               pDevice,
               tempPath,
               D3DX_DEFAULT_NONPOW2,
               D3DX_DEFAULT_NONPOW2,
               0,
               0,
               D3DFMT_FROM_FILE,
               D3DPOOL_MANAGED,
			   it->linearfilter?D3DX_FILTER_LINEAR:D3DX_FILTER_POINT,
               0,
               0,
               NULL,
               NULL,
               &tex.tex);
		if FAILED(hr){
			tex.tex = NULL;
		}
		lookupTextures.push_back(tex);
	}

	shaderLoaded = true;

	return true;
}