0
\$\begingroup\$

I have an issue where my program renders a black screen on other computers. I narrowed it down to when a different graphics card is being used. When I run the program using Integrated Graphics (default) it works just fine. However, when I run the program using High-Performance NVIDIA Processor it just shows a black screen.

I am using non-static Glew32 that I made using CMAKE specifically for Visual Studio 11 2012 Win32. Glew experiment is set to true.

Shader errors output to log file. (There are none right now)


Main Question: Is there a specific way of setting up and rendering OpenGL for NVIDIA Graphics so that it renders properly, and not a black screen? Alternatively, is there a way to setup and use OpenGL so it works on every graphics card?


Edit: nvcompatlog.txt: Trying to draw without a program bound.

(Is this a big clue as to what is wrong? I can not find anything about how to solve this in any specific google search.)

I'm assuming this means my shader program is not being bound before I am rendering. So there must be something there that NVIDIA does not like.

I have another shader that just renders with Ortho view fonts/UIelements, and those render just fine ontop of the black screen.

I stripped my shader down to pretty much nothing. Got rid of all glGetUniform calls to uniforms that do not exist, all variables that aren't used are gone. Still black screen.


OS: Windows 8.1, 64-bit

GPU: GeForce GTX 970M


Source Code:

Generating VBO, VAO, etc.

    glGenVertexArrays( 1, &mesh->GL_VBO_ID );
    glBindVertexArray( mesh->GL_VBO_ID );
    CheckGLError();

    glEnableVertexAttribArray ( 0 );
    glEnableVertexAttribArray ( 1 );
    glEnableVertexAttribArray ( 2 );
    CheckGLError();

    glGenBuffers ( 1, &mesh->GL_VertexBuffer_ID );
    glGenBuffers ( 1, &mesh->GL_IndexBuffer_ID );
    CheckGLError();

    glBindBuffer ( GL_ARRAY_BUFFER, mesh->GL_VertexBuffer_ID );
    CheckGLError();

    unsigned int totalVertBufferSizeBYTES = numIndicesInIndexArray * sizeof ( sVertex_p4t4n4 ); ;
    glBufferData ( GL_ARRAY_BUFFER, totalVertBufferSizeBYTES, pTempVertArray, GL_DYNAMIC_DRAW );
    CheckGLError();

    unsigned int bytesInOneVertex = sizeof( sVertex_p4t4n4 );
    unsigned int byteOffsetToPosition = offsetof( sVertex_p4t4n4, Pos );        
    unsigned int byteOffsetToNormal = offsetof( sVertex_p4t4n4, Normal );   
    unsigned int byteOffsetToUVCoords = offsetof( sVertex_p4t4n4, TexUVx2 );

    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, bytesInOneVertex, (GLvoid*)byteOffsetToPosition );
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, bytesInOneVertex, (GLvoid*)byteOffsetToUVCoords );
    glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, bytesInOneVertex, (GLvoid*)byteOffsetToNormal );
    CheckGLError();

    glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, mesh->GL_IndexBuffer_ID );
    CheckGLError();

    unsigned int sizeOfIndexArrayInBytes = numIndicesInIndexArray * sizeof( GLuint );

    glBufferData ( GL_ELEMENT_ARRAY_BUFFER, sizeOfIndexArrayInBytes, pIndexArrayLocal, GL_DYNAMIC_DRAW);
    CheckGLError();

    glBindVertexArray( 0 );
    CheckGLError();

Rendering

glBindVertexArray ( pGameObject->GL_VBO_ID );
unsigned int numberOfIndices = pGameObject->numTriangles * 3;
glDrawElements( GL_TRIANGLES, numberOfIndices, GL_UNSIGNED_INT, (GLvoid*)0);
CheckGLError();

Create Window

case WM_CREATE:
    {
        this->m_hdc = GetDC(hWnd);
        setupPixelFormat();

        int attribs[] = {
            WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
            WGL_CONTEXT_MINOR_VERSION_ARB, 0,
        0};

        // Create temporary context to get a pointer to the function
        HGLRC tmpContext = wglCreateContext(m_hdc);
        // Make it current
        wglMakeCurrent(this->m_hdc, tmpContext);

        //Get the function pointer
        wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");

        // If this is NULL then OpenGL 4.0 is not supported
        if ( !wglCreateContextAttribsARB )
        {
            MessageBox(NULL, "OpenGL 4.0 is not supported, falling back to GL #.#", "An error occurred", MB_ICONERROR | MB_OK);
            this->m_hglrc = tmpContext;
        }
        else
        {
            //Create an OpenGL 4.0 context using the new function
            this->m_hglrc = wglCreateContextAttribsARB(this->m_hdc, 0, attribs);
            // Delete the temporary context
            wglDeleteContext(tmpContext);
        }

        // Make the GL context current
        wglMakeCurrent(this->m_hdc, this->m_hglrc);

        // We are running!
        this->m_bIsRunning = true;
    }
    break;

Vertex Shader

#version 400

layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_UV_x2;
layout(location=2) in vec4 in_Normal;

out vec4 ex_PositionWorld;
out vec4 ex_Normal;
out vec4 ex_UV_x2;

uniform mat4 ModelMatrix;   
uniform mat4 RotationMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;

void main(void)
{
    mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
    gl_Position = MVP * in_Position;

    ex_PositionWorld = ModelMatrix * in_Position;
    ex_Normal = RotationMatrix * normalize(in_Normal);
    ex_UV_x2 = in_UV_x2;

    return;
}

Fragment Shader

#version 400

// in from vertex shader
in vec4 ex_PositionWorld;
in vec4 ex_Normal;
in vec4 ex_UV_x2;

// Default colour output
out vec4 out_Colour;

// Lights
struct LightDesc
{
    vec3 position;
    vec3 direction;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float attenConst;
    float attenLinear;
    float attenQuad;
    float angle;
};
const int NUMLIGHTS = 10;
uniform LightDesc lights[NUMLIGHTS];

// Material
struct MaterialDesc
{
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
};
const int NUMMATERIALS = 1;
uniform MaterialDesc materials[NUMMATERIALS];
int curMat = 0;

// 1 Texture
uniform sampler2D Texture00;

// 1 CubeMap
uniform samplerCube SamplerCube00;  // Used mostly for skybox. (Like to reserve for skybox reflections if illum set

// Shader ID
uniform int ShaderId;

// Camera
uniform vec3 eye;

vec3 ADSLightModel( in vec3 Normal, 
                    in vec3 Position, 
                    in int LightIndex );

void main(void)
{
// The SkyBox
    if ( ShaderId == 1 )
    {
        vec4 colour = texture( SamplerCube00, ex_Normal.xyz );

        out_Colour = vec4(colour.xyz, 1.0f);

        return;
    }   

    vec4 colour = texture( Texture00, ex_UV_x2.xy);

    vec3 lightContrib = vec3(0.0f, 0.0f, 0.0f);
    for (int lightIdx = 0; lightIdx < 10; lightIdx++)
    {
        lightContrib += ADSLightModel(ex_Normal.xyz, ex_PositionWorld.xyz, lightIdx);
    }

    colour *= lightContrib;
    colour = clamp(colour, 0.0f, 1.0f);

    out_Colour = vec4(colour.xyz, 1.0f);

    return;
}

vec3 ADSLightModel( in vec3 Normal, 
                    in vec3 Position, 
                    in int LightIndex )
{
    if ( length(lights[LightIndex].direction) != 0.0f )
    {
        vec3 diff = normalize(Position - lights[LightIndex].position);
        if ( dot(diff, lights[LightIndex].direction) < lights[LightIndex].angle )
            return vec3(0.0f, 0.0f, 0.0f);
    }

    // normal, light, view, and light reflection vectors
    vec3 norm =     normalize( Normal );
    vec3 lightv =   normalize( lights[LightIndex].position - Position);
    vec3 viewv =    normalize( eye - Position );
    vec3 refl =     -( reflect( lightv, norm ) );

    // ambient light computation
    vec3 ambient = materials[curMat].ambient * lights[LightIndex].ambient;

    // diffuse light computation
    vec3 diffuse = max(0.0f, dot(lightv, norm))
                   * materials[curMat].diffuse
                   * lights[LightIndex].diffuse;// myLightDiffuse;

    // Calculate Attenuation
    float dist = distance( Position, lights[LightIndex].position ); 
    float atten = 1.0f /( lights[LightIndex].attenConst + 
                          lights[LightIndex].attenLinear * dist +
                          lights[LightIndex].attenQuad * dist * dist );

    diffuse *= atten;

    // specular light computation
    vec3 specular = vec3( 0.0f, 0.0f, 0.0f );   
    if( dot(lightv, norm) > 0.0f )
    {
        specular = pow( max(0.0f, dot(viewv,refl)), materials[curMat].shininess)
                    * materials[curMat].specular
                    * lights[LightIndex].specular;// // myLightSpecular;
        specular *= atten;
    }

    return clamp( ambient + diffuse + specular, 0.0f, 1.0f );
}

ErrorLog: (There were no errors in log at one point, and black screen was still a result) The only error previously was when glDrawElements was called. Don't focus directly on these errors to answer my question. This is just here for extra information.

[cGameWindow.cpp:191] INVALID_ENUM   // (Right after GlewInit() *not false*)
4.00 NVIDIA via Cg compiler
[cShaderManager.cpp:112] INVALID_OPERATION  (glUseProgram)
[cRenderManager.cpp:312] INVALID_OPERATION  (glGetUniformLocation)
[cRenderManager.cpp:232] INVALID_OPERATION  (glClearColor)
[cRenderManager.cpp:357] INVALID_OPERATION  (glUniform...)
[cRenderManager.cpp:662] INVALID_OPERATION  (glUniform...)
[cRenderManager.cpp:685] INVALID_OPERATION
[cRenderManager.cpp:401] INVALID_OPERATION
[cRenderManager.cpp:410] INVALID_OPERATION
[cRenderManager.cpp:662] INVALID_OPERATION
[cRenderManager.cpp:591] INVALID_OPERATION
[cRenderManager.cpp:509] INVALID_OPERATION
[cRenderManager.cpp:662] INVALID_OPERATION
[cRenderManager.cpp:509] INVALID_OPERATION
[cRenderManager.cpp:662] INVALID_OPERATION
...
...

ErrorLog With stripped fragment shader (Minimal stuff)

[cGameWindow.cpp:191] INVALID_ENUM
4.00 NVIDIA via Cg compiler
\$\endgroup\$
  • \$\begingroup\$ Not a fix, but curious if the problem gets turned around if you version your shaders with #version 440 instead of 400 \$\endgroup\$ – Niels Mar 15 '16 at 15:03
  • \$\begingroup\$ Also, possibly related hub.jmonkeyengine.org/t/invalidenum-1208-wont-go-away/33755/16 \$\endgroup\$ – Niels Mar 15 '16 at 15:10
  • \$\begingroup\$ @Niels No change in result. \$\endgroup\$ – mythos Mar 15 '16 at 16:12
1
\$\begingroup\$

Main Question: Is there a specific way of setting up and rendering OpenGL for NVIDIA Graphics so that it renders properly, and not a black screen?

NVIDIA graphics cards are no different from any other cards seen from an OpenGL perspective. Different behavior on different platforms may exist as a result of: - Different capabilities. Some cards may tolerate bigger uniform storage than others. OpenGL standard often require a ridiculous minimum leaving how much is needed to please custumers to the vendors to decide. - Bug in the driver. - Your code is reliant on undefined behavior. This may work perfectly well for you on many platforms, in some cases without warnings.

Alternatively, is there a way to setup and use OpenGL so it works on every graphics card?

Sure. Stay within the limitations of your platform. Review your code against the OpenGL standard and look for definitions not matching your required behavior. If reliant on extension, check for them at context creation and shutdown if not found. If any OpenGL error is generated your code should be considered utterly broken. One error is enough.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.