【问题标题】:Two shaders on one object一个对象上的两个着色器
【发布时间】:2015-12-02 16:31:39
【问题描述】:

我的一个对象上的多重着色器有问题。 这是我的渲染代码:

#include "MeshRenderer.h"

ForwardAmbient* shader1;
ForwardDirectional* shader2;

MeshRenderer::MeshRenderer(Obj& obj) :
    meshObject(obj)
{
    shader1 = new ForwardAmbient(vec3(1, 1, 1));
    shader2 = new ForwardDirectional(vec3(1, 0, 0), vec3(1, 1, 1));
}

MeshRenderer::~MeshRenderer()
{

}

void MeshRenderer::Render(RenderingCore* rc)
{
    //for (Shader* shader : meshObject.shaders)
    //{

    //}

    shader1->Bind();
    shader1->UpdateShader(rc, transform, meshObject.material);
    meshObject.material->GetTexture()->Bind(0);
    meshObject.mesh->Render();

    shader2->Bind();
    shader2->UpdateShader(rc, transform, meshObject.material);
    meshObject.material->GetTexture()->Bind(0);
    meshObject.mesh->Render();

    /*
    meshObject.shader->Bind();
    meshObject.shader->UpdateShader(rc, transform, meshObject.material);
    meshObject.material->GetTexture()->Bind(0);
    meshObject.mesh->Render();
    */
}

环境光.vs:

#version 120
attribute vec3 position;
attribute vec2 texCoord;
attribute vec3 normal;

varying vec2 texCoord0;

uniform mat4 transform;
uniform mat4 projection;

void main()
{
    gl_Position = (projection * transform) * vec4(position, 1);
    texCoord0 = texCoord;
}

环境光.fs:

#version 120

varying vec2 texCoord0;

uniform vec3 ambientLight;
uniform float alpha;
uniform sampler2D sampler;

void main()
{
    gl_FragColor = texture2D(sampler, texCoord0.xy) * vec4(ambientLight,  alpha);
}

定向光.vs

#version 120

attribute vec3 position;
attribute vec2 texCoord;
attribute vec3 normal;

varying vec2 texCoord0;
varying vec3 normal0;
varying vec3 worldPos0;

uniform mat4 transform;
uniform mat4 projection;

void main()
{
    gl_Position = (projection * transform) * vec4(position, 1);
    texCoord0 = texCoord;
    normal0 = (transform * vec4(normal, 0)).xyz;
    worldPos0 = (transform * vec4(position, 1)).xyz;
}

定向光.fs

#version 120

varying vec2 texCoord0;
varying vec3 normal0;
varying vec3 worldPos0;

uniform vec3 color;
uniform float alpha;

uniform vec3 direction;
uniform float specularIntensity;
uniform float specularPower;
uniform vec3 eyePosition;

uniform sampler2D sampler;

vec4 calcLight(vec3 color, float alpha, vec3 direction, vec3 normal)
{
    float diffuseFactor = dot(normal, -direction);

    vec4 diffuseColor = vec4(0,0,0,0);
    vec4 specularColor = vec4(0,0,0,0);

    if(diffuseFactor > 0)
    {
        diffuseColor = vec4(color, 1.0) * diffuseFactor;

        vec3 directionToEye = normalize(eyePosition - worldPos0);
        vec3 reflectDirection = normalize(reflect(direction, normal));

        float specularFactor = dot(directionToEye, reflectDirection);
        specularFactor = pow(specularFactor, specularPower);

        if(specularFactor > 0)
        {
            specularColor = vec4(color, 1.0) * specularIntensity * specularFactor;
        }
    }

    return diffuseColor + specularColor;
}

vec4 calcDirectionalLight(vec3 color, float alpha, vec3 direction, vec3 normal)
{
    return calcLight(color, alpha, -direction, normal);
}

void main()
{
    gl_FragColor = texture2D(sampler, texCoord0.xy) *     calcDirectionalLight(color, 1, direction, normalize(normal0));
}

结果如下: http://imgur.com/Bawny2P 只渲染环境光,没有定向光

【问题讨论】:

  • 你使用什么库?看起来您的 Render 函数中有两个单独的渲染通道。您似乎假设多次调用 mesh->Render() 会导致单个着色器效果的某种聚合,但我无法想象会是这种情况。
  • 您是否启用了混合功能?
  • @OpenKastle 我正在使用 OpenGL 库、glew 和 glfw。 BDL 是的,glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  • @MisterVento3 我使用相同的库,但我不熟悉Bind()UpdateShader()Render() 调用,所以我假设您自己编写了这些。如果我们能看到所有相关的代码,那会很有帮助。
  • 这实际上只是在同一个缓冲区上过度绘制。将所有光照计算放在一个着色器/程序中,或者像现代渲染器一样对光照使用多通道渲染。

标签: c++ opengl rendering shader


【解决方案1】:

你的问题是这样的:

shader1->Bind();
shader1->UpdateShader(rc, transform, meshObject.material);
meshObject.material->GetTexture()->Bind(0);
meshObject.mesh->Render();

shader2->Bind();
shader2->UpdateShader(rc, transform, meshObject.material);
meshObject.material->GetTexture()->Bind(0);
meshObject.mesh->Render();

OpenGL 不知道什么是“对象”。它一次只绘制点、线和三角形。为了解决深度重叠,使用了深度缓冲区方法。当您使用完全相同的绘图调用 (meshObject.mesh->Render) 并启用所有相同的顶点设置和深度测试时,两个绘图调用之一将胜过另一个。

另外,更重要的是,绘图调用不会“堆叠”。您根本无法通过多次绘制相同的东西来组合着色器;它可能适用于增材工艺。但这是在找错树:您不是在节省额外的工作,而是在重复要完成的工作量。

您应该做的是将两个着色器合并为一个,并使用合并的着色器仅绘制一次几何体。

【讨论】:

  • 谢谢,我解决了这个问题,但我有新问题,如何解决方向灯:imgur.com/uLEtoVF,我的代码:pastebin.com/6xyzERqC
  • @MisterVento3:看起来不像着色器,而是几何问题。图像中出现的内容通常是使用共享顶点的原因,即对与其接壤的立方体的所有 3 个面使用相同的顶点。一个顶点是整个元组[position, normal, …],如果你只改变一个if,你正在处理一个完全不同的顶点。立方体的每个面的法线都不同,因此您有不同的顶点。
猜你喜欢
  • 2019-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多