C++ OpenGL to Irrlicht (Using OpenGL functions in irrlicht)

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
LosNir
Posts: 43
Joined: Wed Dec 19, 2007 6:38 pm
Location: Israel
Contact:

C++ OpenGL to Irrlicht (Using OpenGL functions in irrlicht)

Post by LosNir »

Hi. I'm trying to port a pure written OpenGL Shader Program (not .glsl files!) to pure irrlicht functions.

How do I access OpenGL functions like "glCreateShader" or "glUniform1f" in irrlicht? Something like:

Code: Select all

ClassToHandleShaders* useSahders = new ClassToHandleShaders();
useShaders->createShader(X, Y, Z);
And this will automatically call the currently used driver pure functions (When using OpenGL it will call glCreateShader, and in d3d it will call it's equivalent).

I saw these functions implemented in "COpenGLSLMaterialRenderer.cpp" and some other files, but I can't seem to figure out where they are being used in irrlicht.

Thanks!
ent1ty
Competition winner
Posts: 1106
Joined: Sun Nov 08, 2009 11:09 am

Post by ent1ty »

irrRenderer 1.0
Height2Normal v. 2.1 - convert height maps to normal maps

Step back! I have a void pointer, and I'm not afraid to use it!
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Just read example 10, all those internal functions are called automatically for you when creating a shader based material.
LosNir
Posts: 43
Joined: Wed Dec 19, 2007 6:38 pm
Location: Israel
Contact:

Post by LosNir »

Yeah I know that, that's what Irrlicht is for. But I have some tons of OpenGL functions and I don't know which is which. Which is done by function X of irrlicht and which is done by function Y of irrlicht.

I have this code for exmaple:

Code: Select all

Program::Program(int files, char** fileNames, char *options) {
    program = -1;
    vertexShader = -1;
    fragmentShader = -1;
    geometryShader = -1;

    const char **contents = (const char**) malloc((files + 2) * sizeof(char*));

    int i;
    bool geo = false;
    for (i = 0; i < files; ++i) {
        contents[i + 2] = textFileRead(fileNames[i]);
        if (strstr(contents[i + 2], "_GEOMETRY_") != NULL) {
            geo = true;
        }
    }

    printf("LOADING %s\n", fileNames[files - 1]);

    if (program == -1) {
        program = glCreateProgram();
        vertexShader = glCreateShader(GL_VERTEX_SHADER);
        fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
        glAttachShader(program, vertexShader);
        glAttachShader(program, fragmentShader);
        assert(glGetError() == 0);
    }

    contents[0] = "#define _VERTEX_\n";
    contents[1] = options == NULL ? "" : options;
    glShaderSource(vertexShader, files + 2, contents, NULL);
    glCompileShader(vertexShader);
    checkShader(vertexShader);
    assert(glGetError() == 0);

    if (geo) {
        geometryShader = glCreateShader(GL_GEOMETRY_SHADER_EXT);
        glAttachShader(program, geometryShader);
        contents[0] = "#define _GEOMETRY_\n";
        contents[1] = options == NULL ? "" : options;
        glShaderSource(geometryShader, files + 2, contents, NULL);
        glCompileShader(geometryShader);
        printShaderLog(geometryShader);
        glProgramParameteriEXT(program, GL_GEOMETRY_INPUT_TYPE_EXT, GL_TRIANGLES);
        glProgramParameteriEXT(program, GL_GEOMETRY_OUTPUT_TYPE_EXT, GL_TRIANGLE_STRIP);
        glProgramParameteriEXT(program, GL_GEOMETRY_VERTICES_OUT_EXT, 3 * 5);
    }

    contents[0] = "#define _FRAGMENT_\n";
    glShaderSource(fragmentShader, files + 2, contents, NULL);
    glCompileShader(fragmentShader);
    checkShader(fragmentShader);
    assert(glGetError() == 0);

    for (i = 0; i < files; ++i) {
        free((void*) contents[i + 2]);
    }

    glBindAttribLocation(program, 1, "normal");
    glBindAttribLocation(program, 2, "color");

    glLinkProgram(program);
    GLint logLength;
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0) {
        char *log = new char[logLength];
        glGetProgramInfoLog(program, logLength, &logLength, log);
        printf("%s", log);
    }

    if (checkProgram(program)) {
        assert(glGetError() == 0);
    } else {
        printShaderLog(vertexShader);
        printShaderLog(fragmentShader);
        exit(-1);
    }
}
What could be the Irrlicht equivalent, that's my question actually.
Of course I don't expect anyone to convert this code, I'm just showing what I'm dealing with.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

You have to create all three input shaders at once, and pass them to the Irrlicht function. The geometry shader parameters can be passed there as well. AttribLocation is fixed, so adapt to the vertex structure you are using.
LosNir
Posts: 43
Joined: Wed Dec 19, 2007 6:38 pm
Location: Israel
Contact:

Post by LosNir »

I've made some more reading.
The "Irrlicht function" you are talking about is addHighLevelShaderMaterial / FromFiles.. right?

I've taken another look at the code, and it seems it loads the shader files, adds some #define lines and adds the options passed.
If you take a look at the code, assuming it's being called like:

Code: Select all

    char* files[2];
    char options[512];
    files[0] = "Resources/shaders/water/atmosphere.glsl";
    files[1] = "Resources/shaders/water/ocean.glsl";
    sprintf(options, "#define %sSEA_CONTRIB\n#define %sSUN_CONTRIB\n#define %sSKY_CONTRIB\n#define %sCLOUDS\n#define %sHARDWARE_ANISTROPIC_FILTERING\n",
        seaContrib ? "" : "NO_", sunContrib ? "" : "NO_", skyContrib ? "" : "NO_", cloudLayer ? "" : "NO_", manualFilter ? "NO_" : "");

render = new Program(2, files, options);
Variable `contents` is a 4 cell array, last 2 induces (2,3) holds the shader data read by `textFileRead`, and 2 first induces (0, 1) holds the options and the definitions of vertex / fragment.

With the above information, we can assume this:

1. Since Irrlicht call's `glCreateShader` and `glAttachShader` automatically when calling `addHighLevelShaderMaterial ` (we need that at the first if condition) we can "forget" them.

2. We know`glShaderSource` requires a char* array, which is parameter named "string" which contains the shader code it self. Here: http://www.opengl.org/sdk/docs/man/xhtm ... Source.xml

3. We know that `contents` is being passed to `glShaderSource` as parameter "string", and we also know that the size of `contents` (4) is being passed to parameter "length" which should be the size of parameter "string".

4. So everything is correct by now. However, in Irrlicht, parameter "count" is being hard-coded to 1 as in:

Code: Select all

Driver->extGlShaderSource(shaderHandle, 1, &shader, NULL);
From `COpenGLSLMaterialRenderer.cpp`.

This requires us to pass a 1-cell array to parameter "string", meaning I should merge `contents` to one (char*) variable, delimiting each cell from `contents` array with a line break. Right?

Could you elaborate more on "glBindAttribLocation"?

If I made some wrong assumptions please let me know! And sorry for that very-long-too-obvious-post, I just like to lay down information as it is in steps so it's easier to understand :)
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, you're right with your assumptions. The glBindAttribLocation defines the semantics of the structural elements of each vertex. Since Irrlicht does not use a flexible vertex format, the locations are predefined and are automatically defined. You just have to make sure that your shaders expect the data in those predefined locations.
LosNir
Posts: 43
Joined: Wed Dec 19, 2007 6:38 pm
Location: Israel
Contact:

Post by LosNir »

Alright. Before I continue, what is exactly the value returned from `addHighLevelShaderMaterial`? glCreateProgram?
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

It's an internal ID, which should be used as a MaterialType when using this material.
LosNir
Posts: 43
Joined: Wed Dec 19, 2007 6:38 pm
Location: Israel
Contact:

Post by LosNir »

I've made some progress. Some of the shaders are loaded successfully, but some giving me compile error:
[GUI Engine] Sucessfully loaded font 'fonts/arial12.bmp' as `defaultFont`!
Loading Shader.. ocean.glsl
Loading Shader.. sky.glsl
GLSL shader failed to compile

0(532) : error C1008: undefined variable "screenToCamera"

Loading Shader.. skymap.glsl
GLSL shader failed to compile

0(553) : error C1008: undefined variable "sunDir"
0(565) : error C1008: undefined variable "sunDir"

Loading Shader.. clouds.glsl
GLSL shader failed to compile

0(526) : error C1008: undefined variable "worldToScreen"
What could be the problem? Here is the code: http://codetrunk.com/f8b092a5

`loadRequiredShaders` is being called.

EDIT:

Got it working. It was a null termination problem that took forever to fix.
LosNir
Posts: 43
Joined: Wed Dec 19, 2007 6:38 pm
Location: Israel
Contact:

Post by LosNir »

Another question, when calling "setPixelShaderConstant" on the ShaderConstantCallback, what value of count should I use for the following types?

sampler2D
sampler3D
float

Thanks.
stefbuet
Competition winner
Posts: 495
Joined: Sun Dec 09, 2007 4:13 pm
Location: france

Post by stefbuet »

You put your texture on the model with node->setMaterialTexture(ID, myTexture);
where ID = 0, 1, 2, 3, .....

And in the setPixelShader constant, you just send the texture ID like this :

Code: Select all

int textureAddress=0;
        services->setPixelShaderConstant("mySample2D", (float*)(&textureAdress),1); 
Currentlly 3D texture are not supported by Irrlicht, BUT
thespecial1 managed to use them with shaders, maybe you should ask him some tips about it.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Yeah, make sure the texture id is stored in an INT and passed as a float pointer like stefbuet's example.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
LosNir
Posts: 43
Joined: Wed Dec 19, 2007 6:38 pm
Location: Israel
Contact:

Post by LosNir »

Yup, for example I did:

Code: Select all

rServices->setPixelShaderConstant("skyIrradianceSampler", &this->m_irradianceUnit, 1);
LosNir
Posts: 43
Joined: Wed Dec 19, 2007 6:38 pm
Location: Israel
Contact:

Post by LosNir »

Code: Select all

    float *data = new float[16*64*3];
    FILE *f = fopen("data/irradiance.raw", "rb");
    fread(data, 1, 16*64*3*sizeof(float), f);
    fclose(f);
    glActiveTexture(GL_TEXTURE0 + IRRADIANCE_UNIT);
    glGenTextures(1, &irradianceTex);
    glBindTexture(GL_TEXTURE_2D, irradianceTex);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F_ARB, 64, 16, 0, GL_RGB, GL_FLOAT, data);
    delete[] data;
How can I turn this code into Irrlicht equivalent?

Code: Select all

this->waterSceneNode->setMaterialTexture(IRRADIANCE_UNIT, this->m_irrlichtDevice->getVideoDriver()->getTexture("data/irradiance.raw"));
Will this do the work?
Post Reply