Sign in to follow this  
Hector San Roman Lanza

Is it possible to have a vertex shader and the fragment shader in the same file?

Recommended Posts

Radikalizm    4807
You could always create a wrapper file in a format like XML in which you put both your fragment and vertex shaders. You can then parse the XML file and read the two different sources and compile them as normal.
I think you could also pull this off with some pre-processor magic though

Share this post


Link to post
Share on other sites
alh420    5995
[quote name='Radikalizm' timestamp='1349884506' post='4988749']
I think you could also pull this off with some pre-processor magic though
[/quote]

The opengl api requires you to split them before loading, so I don't think the preprocessor will help you?
But maybe just a simple marker in the file you can look for?

[source lang="cpp"]#vertex
main() {
..
}

#fragment
main() {
...
}
[/source]
Should be simple to write some loader code that finds and split the file on the markers

Edit:
I realized how to do it with preprocessor, should also work [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
Just have a vertex_main and a fragment_main that you patch in a #define for at the top of the file at load.

Interesting concept, might be useful Edited by Olof Hedman

Share this post


Link to post
Share on other sites
Radikalizm    4807
[quote name='Olof Hedman' timestamp='1349887700' post='4988768']
I realized how to do it with preprocessor, should also work
Just have a vertex_main and a fragment_main that you patch in a #define for at the top of the file at load.

Interesting concept, might be useful
[/quote]

Yeah that's what I was thinking as well, haven't tested it though but I believe this should work.

Share this post


Link to post
Share on other sites
I used a marker and do a quick string function after I load the file to replace the markers with 0's and save offsets, Then I pass those pointers to the compiler. [vertex shader] [fragment shader] [geometry shader] is what I use. I also have shader definition which allows me to create indexes to attributes and other data opengl needs to index data.


So it ends up looking like this.
[source lang="plain"]
[Shader Definition]

[0] = attribute vPosition
[1] = uniform mModelView
[2] = uniform mProjection

frag fragColor0

[Vertex shader]
#version 150

in vec3 vPosition;

uniform mat4 mModelView;
uniform mat4 mProjection;

void main(void)
{
vec4 posTemp = mModelView * vec4(vPosition, 1.0);
gl_Position = mProjection * posTemp;
}


[Fragment shader]
#version 150


out vec4 fragColor0;

void main (void)
{
// Save it squared
fragColor0 = vec4(0, 0, 0, 0);
}

[/source] Edited by RevenantBob

Share this post


Link to post
Share on other sites
Cornstalks    7030
A different way to do with with macro magic is something like:
[b]Shader.glsl[/b]
[code]
#ifdef COMPILING_VERTEX_SHADER

// vertex shader
void main()
{}

#endif
#ifdef COMPILING_FRAGMENT_SHADER

// fragment shader
void main()
{}

#endif
[/code]

[b]Source File.cpp[/b]
[code]
std::string fileContents = fileToString("Shader.glsl"); // load it as a string
std::string compilingString = "#define COMPILNG_VERTEX_SHADER\n" + fileContents;
// load vertex shader...
compilingString = "#define COMPILING_FRAGMENT_SHADER\n" + fileContents;
// load fragment shader...
[/code]

Share this post


Link to post
Share on other sites
Radikalizm    4807
[quote name='Cornstalks' timestamp='1349901383' post='4988845']
A different way to do with with macro magic is something like:
[b]Shader.glsl[/b]
[code]
#ifdef COMPILING_VERTEX_SHADER

// vertex shader
void main()
{}

#endif
#ifdef COMPILING_FRAGMENT_SHADER

// fragment shader
void main()
{}

#endif
[/code]

[b]Source File.cpp[/b]
[code]
std::string fileContents = fileToString("Shader.glsl"); // load it as a string
std::string compilingString = "#define COMPILNG_VERTEX_SHADER\n" + fileContents;
// load vertex shader...
compilingString = "#define COMPILING_FRAGMENT_SHADER\n" + fileContents;
// load fragment shader...
[/code]
[/quote]

Yep, that's pretty much what Olof Hedman and I were talking about, should work just fine.

Share this post


Link to post
Share on other sites
mhagain    13430
I use Cornstalks' suggestion and it works great; it's nice that glShaderSource takes an array of strings as it's source param because you can just pop in the appropriate #define in the first array slot.

It's also be possible to extend that to support multiple shaders of the same type in a single file, and all other combinations with another #define such as:
[code]#define MyVertexShaderEntryPointName main

void MyVertexShaderEntryPointName ()
{
// do stuff....[/code]

Share this post


Link to post
Share on other sites
alh420    5995
[quote name='Radikalizm' timestamp='1349907409' post='4988886']
[quote name='Cornstalks' timestamp='1349901383' post='4988845']
A different way to do with with macro magic is something like:
[/quote]

Yep, that's pretty much what Olof Hedman and I were talking about, should work just fine.
[/quote]

Yep. I like my suggestion (and mhagain's) better though, that is to re-define the main function name.
That way you don't have to clutter your source file with #ifdefs, and the other main should be removed at link time. Edited by Olof Hedman

Share this post


Link to post
Share on other sites
larspensjo    1561
[quote name='ShotoReaper' timestamp='1349881679' post='4988741']
Just like HLSL.
[/quote]
You didn't say why you want them in the same file. I suppose there is a design reason for that.

A simple solution is to put the shaders in initialized strings. Easy, but does it satisfy your (unspoken) requirements?

Share this post


Link to post
Share on other sites
I get the error 1281, 'Invalid value' from the function glAttachShader.


Shader.hpp

[CODE]
class Shader : public object
{
public:
Shader();
virtual ~Shader();
GLuint ID;
void Load(const char* filename);
protected:
private:
GLuint vertexShaderID,
fragmentShaderID;
void Initialize(void);

void CreateShader(GLuint shader_id, std::string shader, GLenum type_shader);
};
[/CODE]

Shader.cpp

[CODE]void Shader::Load(const char* filename)
{
ifstream in(filename, ios::binary);
if(!in)
{
cerr << "Could open file" << filename << endl; // Lanzamos un mensaje de error
exit(1); // exit(1) usado para abortar el programa
}

std::string glsl_source((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());

in.close();

if(glsl_source.length() == 0)
{
exit(1);
}
std::string fs_shader = "#define COMPILING_FS\n" + glsl_source;
std::string vs_shader = "#define COMPILING_VS\n" + glsl_source;
std::cout<<vs_shader<<std::endl;
ID = glCreateProgram();
CreateShader(fragmentShaderID,fs_shader,GL_FRAGMENT_SHADER);
CreateShader(vertexShaderID,vs_shader,GL_VERTEX_SHADER);
Initialize();
}
void Shader::CreateShader(GLuint shader_id, std::string shader, GLenum type_shader)
{
shader_id = glCreateShader(type_shader);
const char* glsl_cstr;
glShaderSource(shader_id, 1, &(glsl_cstr=shader.c_str()),NULL);
glCompileShader(shader_id);
ExitOnGLError("Could compile shader");
}
void Shader::Initialize(void)
{
glAttachShader(ID, fragmentShaderID); // Error in here
ExitOnGLError("Could attach fragmentshader");
glAttachShader(ID, vertexShaderID);
ExitOnGLError("Could attach vertexshader");
glLinkProgram(ID);
ExitOnGLError("Could link program");
}
[/CODE]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this