Jump to content

  • Log In with Google      Sign In   
  • Create Account

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


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
13 replies to this topic

#1 ShotoReaper   Members   -  Reputation: 149

Like
0Likes
Like

Posted 10 October 2012 - 09:07 AM

Just like HLSL.

Sponsor:

#2 Cornstalks   Crossbones+   -  Reputation: 6994

Like
0Likes
Like

Posted 10 October 2012 - 09:43 AM

I don't think so. The void main() functions for the vertex shader and fragment shader would conflict.
[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#3 Radikalizm   Crossbones+   -  Reputation: 2885

Like
1Likes
Like

Posted 10 October 2012 - 09:55 AM

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

I gets all your texture budgets!


#4 Olof Hedman   Crossbones+   -  Reputation: 2827

Like
0Likes
Like

Posted 10 October 2012 - 10:48 AM

I think you could also pull this off with some pre-processor magic though


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"]#vertexmain() {..}#fragmentmain() {...}[/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 Posted Image
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, 10 October 2012 - 10:53 AM.


#5 Radikalizm   Crossbones+   -  Reputation: 2885

Like
0Likes
Like

Posted 10 October 2012 - 10:55 AM

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


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

I gets all your texture budgets!


#6 RevenantBob   Members   -  Reputation: 114

Like
2Likes
Like

Posted 10 October 2012 - 02:09 PM

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 mProjectionfrag fragColor0[Vertex shader]#version 150in 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 150out vec4 fragColor0;void main (void){ // Save it squared fragColor0 = vec4(0, 0, 0, 0); }[/source]

Edited by RevenantBob, 10 October 2012 - 02:09 PM.


#7 Cornstalks   Crossbones+   -  Reputation: 6994

Like
3Likes
Like

Posted 10 October 2012 - 02:36 PM

A different way to do with with macro magic is something like:
Shader.glsl
#ifdef COMPILING_VERTEX_SHADER

// vertex shader
void main()
{}

#endif
#ifdef COMPILING_FRAGMENT_SHADER

// fragment shader
void main()
{}

#endif

Source File.cpp
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...

[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#8 Radikalizm   Crossbones+   -  Reputation: 2885

Like
0Likes
Like

Posted 10 October 2012 - 04:16 PM

A different way to do with with macro magic is something like:
Shader.glsl

#ifdef COMPILING_VERTEX_SHADER

// vertex shader
void main()
{}

#endif
#ifdef COMPILING_FRAGMENT_SHADER

// fragment shader
void main()
{}

#endif

Source File.cpp
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...


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

I gets all your texture budgets!


#9 mhagain   Crossbones+   -  Reputation: 7979

Like
0Likes
Like

Posted 10 October 2012 - 07:29 PM

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:
#define MyVertexShaderEntryPointName main

void MyVertexShaderEntryPointName ()
{
    // do stuff....

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#10 Olof Hedman   Crossbones+   -  Reputation: 2827

Like
0Likes
Like

Posted 11 October 2012 - 01:06 AM


A different way to do with with macro magic is something like:


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


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, 11 October 2012 - 01:06 AM.


#11 larspensjo   Members   -  Reputation: 1540

Like
0Likes
Like

Posted 11 October 2012 - 02:36 AM

Just like HLSL.

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?
Current project: Ephenation.
Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/

#12 ShotoReaper   Members   -  Reputation: 149

Like
0Likes
Like

Posted 12 October 2012 - 08:28 AM

Cornstalks,I try use your method.
Thanks for the answers!

Edited by ShotoReaper, 12 October 2012 - 08:31 AM.


#13 ShotoReaper   Members   -  Reputation: 149

Like
0Likes
Like

Posted 12 October 2012 - 08:51 AM

I get the error 1281, 'Invalid value' from the function glAttachShader.


Shader.hpp

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);
};

Shader.cpp

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");
}


#14 ShotoReaper   Members   -  Reputation: 149

Like
0Likes
Like

Posted 12 October 2012 - 09:35 AM

Sorry, I found the problem xDD
When I call CreateShader, I not return the shader id. Therefore FragmentShaderID and VertexShaderID in glAttachShader have value 0.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS