• Advertisement
Sign in to follow this  

Is this a good way to organize and manage shaders?

This topic is 3936 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm pretty new to the whole shaders thing so I'm trying to make a simple class that will hold and manage shaders. I made this class to help me with organizing the many diffferent shaders (incomplete), however everytime I try to use it the program crashes, I'm not sure if it's shader related since I'm using one taken out of a textbook yet it doesn't work at all wherever I try to use it (even in the sample sourcecode).
#include "../common/dxstdafx.h"
#include <vector>


#define NOMINMAX

#ifndef SHADER_H
#define SHADER_H

class Shader
{
public:
	Shader(IDirect3DDevice9* Device);
	IDirect3DDevice9* Device;
	struct Hand
	{
		D3DXHANDLE handle;
		LPCSTR name;
	};
	struct FXCollec
	{
		LPCWSTR fileName;
		LPCWSTR collecName;
		ID3DXEffect* mFX;

		std::vector<Hand> handle;
	};
	std::vector<FXCollec> Effects;

	void CreateEffectFromFile(LPCWSTR collecName, LPCWSTR fileName);
	void GetTechByName(LPCSTR handleName, LPCWSTR collecName);
	void GetHandleByParam(LPCSTR handleName, LPCWSTR collecName, int param);
};

#endif
#include "SHADER.h"

Shader::Shader(IDirect3DDevice9* Device1)
{
	Device = Device1;
}

void Shader::CreateEffectFromFile(LPCWSTR collecName, LPCWSTR filename)
{
	FXCollec temp;

	temp.fileName = filename;
	temp.collecName = collecName;
	Effects.push_back(temp);

	int i;
	for(i = 0; i < Effects.size(); i++)
	{
		if(Effects.collecName = collecName)
			break;
	}

	ID3DXBuffer* errors = 0;
	D3DXCreateEffectFromFile(Device, filename, 
		0, 0, D3DXSHADER_DEBUG, 0, &Effects.mFX, &errors);

	if( errors )
		MessageBox(0, (TCHAR*)errors->GetBufferPointer(), 0, 0);
}

void Shader::GetTechByName(LPCSTR handleName, LPCWSTR collecName)
{
	int collecNum;

	for(collecNum = 0; collecNum < Effects.size(); collecNum++)
	{
		if(Effects[collecNum].collecName == collecName)
			break;
	}

	Hand tech;
	tech.name = handleName;
	tech.handle = Effects[collecNum].mFX->GetTechniqueByName(handleName);
	
	Effects[collecNum].handle.push_back(tech);
}

void Shader::GetHandleByParam(LPCSTR handleName, LPCWSTR collecName, int p)
{
	int collecNum;

	for(collecNum = 0; collecNum < Effects.size(); collecNum++)
	{
		if(Effects[collecNum].collecName == collecName)
			break;
	}

	Hand tech;
	tech.name = handleName;
	tech.handle = Effects[collecNum].mFX->GetParameterByName(0, handleName);

	Effects[collecNum].handle.push_back(tech);
}

as you can see I'm no programmer genius :P Heres the code for the shader that doesn't seem to work (taken from moon-labs.com):
////////////////////////////////////////////////////////////////////////////
// 
// File: tooneffect.txt
// 
// Author: Frank Luna (C) All Rights Reserved
//
// System: AMD Athlon 1800+ XP, 512 DDR, Geforce 3, Windows XP, MSVC++ 7.0 
//
// Desc: Cartoon shader in an effect file.
//          
////////////////////////////////////////////////////////////////////////////

//
// Globals
//

extern matrix WorldViewMatrix;
extern matrix WorldViewProjMatrix;

extern vector Color;
extern vector LightDirection;
extern texture ShadeTex;

//
// Structures
//

struct VS_INPUT
{
    vector position : POSITION;
    vector normal   : NORMAL;
};

struct VS_OUTPUT
{
    vector position : POSITION;
    float2 uvCoords : TEXCOORD;
    vector diffuse  : COLOR;
};
//
// Main
//

VS_OUTPUT Main(VS_INPUT input)
{
    // zero out each member in output
    VS_OUTPUT output = (VS_OUTPUT)0;


    // transform vertex position to homogenous clip space
     output.position = mul(input.position, WorldViewProjMatrix);

    //
    // Transform lights and normals to view space.  Set w
    // components to zero since we're transforming vectors.
    // Assume there are no scalings in the world
    // matrix as well.
    //
    LightDirection.w = 0.0f;
    input.normal.w   = 0.0f;
    LightDirection   = mul(LightDirection, WorldViewMatrix);
    input.normal     = mul(input.normal, WorldViewMatrix);

    //
    // Compute the 1D texture coordinate for toon rendering.
    //
    float u = dot(LightDirection, input.normal);

    //
    // Clamp to zero if u is negative because u
    // negative implies the angle between the light
    // and normal is greater than 90 degrees.  And
    // if that is true then the surface receives
    // no light.
    //
    if( u < 0.0f )
        u = 0.0f;

    // 
    // Set other tex coord to middle.
    //
    float v = 0.5f;


    output.uvCoords.x = u;
    output.uvCoords.y = v;

    // save color
    output.diffuse = Color;
    
    return output;
}

//
// Sampler
//

sampler ShadeSampler = sampler_state
{
    Texture   = (ShadeTex);
    MinFilter = POINT; // no filtering for cartoon shading
    MagFilter = POINT;
    MipFilter = NONE;
};


// 
// Effect
//

technique Toon
{
    pass P0
    {
        vertexShader = compile vs_1_1 Main();

        Sampler[0] = (ShadeSampler);
    }
}

Share this post


Link to post
Share on other sites
Advertisement
Quote:
everytime I try to use it the program crashes
To be honest, I don't know what you expect anyone here to tell you. You've not provided any debugging results - did you step through your code? did you check error values/states? what are the intermediary values? have you checked your logic?...

Static analysis only goes so far - it's hard for anyone to debug code just by looking at a dump of your source files. I can see a lot of places in your code that might explode in your face - but without the context of how it's running and against what data (not just the data you're loading - intermediary states etc..) then they may or may not be dangerous.

If, after some debugging, you still can't figure it out post back here with what you've tested and any relevant results and we'll see what we can do [smile]

hth
Jack

Share this post


Link to post
Share on other sites
Isn't that a pretty dangerous way to handle strings? If I create a string, send it to your manager, then destroy it, your manager will now hold invalid pointers.

Example:

Shader TestShader;
{
std::wstring Filename = L"Shader.fx";
TestShader.CreateEffectFromFile(L"Something", Filename.c_str());
}
TestShader.GetTechByName("SomeTech", L"Something");



When the string Filename goes out of scope, it is destroyed and the next call to GetTechByName might fail.

And you've also made a simple mistake:

int i;
for(i = 0; i < Effects.size(); i++)
{
if(Effects.collecName = collecName)
break;
}


You're assigning when you should be comparing. Which won't work either, since you can't compare c-strings like that. I suggest you use std::string and std::wstring (when you need wide character support), which is far, far better than what you're using.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement