Моя шейдерная программа GLSL работает нормально, но ошибки при попытке ее использовать - как мне это отладить? - PullRequest
1 голос
/ 09 января 2012

Если бы у меня была синтаксическая ошибка в моем GLSL, она не работала бы во время компоновки, не так ли?

В любом случае, я пытался запустить свою программу в glslDevil (никогда раньше не использовал эту программу), и она простопродолжает повторять wglGetCurrentContext().Я не уверен, должен ли он это делать, или он запутался, потому что это приложение CLR.

Есть ли более простой способ проверки синтаксических ошибок в моем коде GLSL?

Этопохоже, это фрагментный шейдер, который вызывает проблему .... вот код, если необходимо:

#version 330

const int MAX_POINT_LIGHTS = 2;

in vec2 TexCoord0;
in vec3 Normal0;
in vec3 WorldPos0;

out vec4 FragColor;

struct BaseLight
{
    vec3 Color;
    float AmbientIntensity;
    float DiffuseIntensity;
};

struct DirectionalLight
{
    struct BaseLight Base;
    vec3 Direction;
};

struct Attenuation
{
    float Constant;
    float Linear;
    float Exp;
};

struct PointLight
{
    struct BaseLight Base;
    vec3 Position;
    Attenuation Atten;
};

uniform int gNumPointLights;
uniform DirectionalLight gDirectionalLight;
uniform PointLight gPointLights[MAX_POINT_LIGHTS];
uniform sampler2D gSampler;
uniform vec3 gEyeWorldPos;
uniform float gMatSpecularIntensity;
uniform float gSpecularPower;

vec4 CalcLightInternal(struct BaseLight Light, vec3 LightDirection, vec3 Normal)
{
    vec4 AmbientColor = vec4(Light.Color, 1.0f) * Light.AmbientIntensity;
    float DiffuseFactor = dot(Normal, -LightDirection);

    vec4 DiffuseColor  = vec4(0, 0, 0, 0);
    vec4 SpecularColor = vec4(0, 0, 0, 0);

    if (DiffuseFactor > 0) {
        DiffuseColor = vec4(Light.Color, 1.0f) * Light.DiffuseIntensity * DiffuseFactor;

        vec3 VertexToEye = normalize(gEyeWorldPos - WorldPos0);
        vec3 LightReflect = normalize(reflect(LightDirection, Normal));
        float SpecularFactor = dot(VertexToEye, LightReflect);
        SpecularFactor = pow(SpecularFactor, gSpecularPower);
        if (SpecularFactor > 0) {
            SpecularColor = vec4(Light.Color, 1.0f) *
                            gMatSpecularIntensity * SpecularFactor;
        }
    }

    return (AmbientColor + DiffuseColor + SpecularColor);
}

vec4 CalcDirectionalLight(vec3 Normal)
{
    return CalcLightInternal(gDirectionalLight.Base, gDirectionalLight.Direction, Normal);
}

vec4 CalcPointLight(int Index, vec3 Normal)
{
    vec3 LightDirection = WorldPos0 - gPointLights[Index].Position;
    float Distance = length(LightDirection);
    LightDirection = normalize(LightDirection);

    vec4 Color = CalcLightInternal(gPointLights[Index].Base, LightDirection, Normal);
    float Attenuation =  gPointLights[Index].Atten.Constant +
                         gPointLights[Index].Atten.Linear * Distance +
                         gPointLights[Index].Atten.Exp * Distance * Distance;

    return Color / Attenuation;
}

void main()
{
    vec3 Normal = normalize(Normal0);
    vec4 TotalLight = CalcDirectionalLight(Normal);

    for (int i = 0 ; i < gNumPointLights ; i++) {
        TotalLight += CalcPointLight(i, Normal);
    }

    FragColor = texture2D(gSampler, TexCoord0.xy) * TotalLight;
}

Редактировать: В частности, я получаю GL_INVALID_OPERATION при вызовеglUseProgram.Документы говорят:

GL_INVALID_OPERATION генерируется, если программа не является программным объектом.

GL_INVALID_OPERATION генерируется, если программа не может быть частью текущего состояния.

GL_INVALID_OPERATION генерируется, если glUseProgram выполняется между выполнением glBegin и соответствующим выполнением glEnd.

Но я не думаю, что это может быть первым или последним случаем, потому что программа работала нормально, пока яподправил шейдер.«не может быть частью нынешнего состояния» не дает мне многого продолжать.

Ответы [ 3 ]

1 голос
/ 09 января 2012

Проблема была в следующем:

struct PointLight
{
    struct BaseLight Base;
    vec3 Position;
    Attenuation Atten;
};

Должно быть просто BaseLight Base, нет struct

А это:

vec4 CalcLightInternal(struct BaseLight Light, vec3 LightDirection, vec3 Normal)

Та же проблема.

Думал, что это выглядело смешно, поэтому я изменил его, и он начал работать.

1 голос
/ 24 октября 2017

Когда программный объект был успешно связан, программный объект можно сделать частью текущего состояния, вызвав glUseProgram. Так что вы должны вызвать программную ссылку перед использованием программы

1 голос
/ 09 января 2012

Я думаю, что одним из возможных объяснений может быть цикл for внутри вашего кода.

В моем скромном опыте всегда следует избегать утверждения for.

Учтите, что OpenGL ES поддерживает только фиксированное количество итераций, и, в вашем случае, поскольку вы основываете его на униформе, я бы изучил его.

Кроме того, учтите, что многие драйверы развертывают оператор for для оптимизации сгенерированного кода.

Другими словами, я бы остановился на более простой версии вашего шейдера, примерно такой:

if (gNumPointLights == 1) {
TotalLight += CalcPointLight(1, Normal);
} else if (gNumPointLights ==  2) {
TotalLight += CalcPointLight(1, Normal);
TotalLight += CalcPointLight(2, Normal);
} else if (gNumPointLights ==  3) {
TotalLight += CalcPointLight(1, Normal);
TotalLight += CalcPointLight(2, Normal);
TotalLight += CalcPointLight(3, Normal);
}

Очевидно, что код можно оптимизировать по стилю и эффективности, но это быстрый старт.

Во всяком случае, реально, у вас не будет тысяч огней одновременно :)

Приветствия

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...