OpenGL阴影映射。在GPU上执行计算?

时间:2016-05-16 04:58:34

标签: c# opengl glsl opentk shadow-mapping

我正在使用一种简单的衰减算法,根据它们与光源的距离使墙壁变暗。

enter image description here

最终目标是开发一种光照贴图系统,其中每个墙的亮度在预通过中计算(包括来自其他墙的阴影),然后该光照图像与墙纹理混合。

enter image description here + enter image description here = enter image description here

除了阴影之外,我还有光照贴图,结果会完全复制着色器代码。问题是它很慢,添加光照阴影检查只会使情况变得更糟。

我的问题是,如何在GPU上执行这些计算?是否需要第三方库/模块,或者可以通过OpenGL本机完成(在我的案例中是OpenTK)?

或者,我很乐意切换到具有立方体阴影贴图的延迟渲染/照明,但我还没有看到任何可以让我了解的信息。

c#lightmap (每面墙运行一次)

public void createLightMap()
{
    // Determine Light Map dimensions
    int LightMapSize = 300; 
    int w = (int)(this.Width * LightMapSize);
    int h = (int)(this.Height * LightMapSize);

    // Create Bitmap
    Bitmap bitmap = new Bitmap(w, h);

    // Fragment testing
    Vector3 fragmentPosition = new Vector3(this.x2, this.Height, this.z2);
    float xIncement = (1f / LightMapSize) * ((x2 - x) / this.Width);
    float zIncement = (1f / LightMapSize) * ((z2 - z) / this.Width);
    float yIncement = (1f / LightMapSize);


    // Calculate Light value for each pixel
    for (int x = 0; x < w; x++) {
        for (int y = 0; y < h; y++)
        {
            // Update fragment position
            fragmentPosition.X = this.x2 -  xIncement -(xIncement * x);
            fragmentPosition.Z = this.z2 - (zIncement * x);
            fragmentPosition.Y = this.Height - (yIncement * y);

            Vector3 totalDiffuse = Vector3.Zero;

            // Iterate through the lights
            for (int n = 0; n < 2; n++)
            {
                Light light = Game.lights[n];
                Vector3 LightPosition = new Vector3(light.Position);
                Vector3 Attenuation = new Vector3(light.Attenuation);
                Vector3 Colour = new Vector3(light.Colour);
                Vector3 toLightVector = LightPosition - fragmentPosition;

                // Return early if wall is facing away from light
                if (Vector3.Dot(this.normalVector, toLightVector.Normalized()) < 0)
                    continue;

                // Calculate vector length (aka, distance from lightsource)
                float distance = (float)Math.Sqrt(toLightVector.X * toLightVector.X + toLightVector.Y * toLightVector.Y + toLightVector.Z * toLightVector.Z);

                // Attenuation
                float attFactor = Attenuation.X + (Attenuation.Y * distance) + (Attenuation.Z * distance * distance);
                Vector3 diffuse = Colour / attFactor;
                totalDiffuse += diffuse;
            }
            // Create bitmap
            var r = (int)(totalDiffuse.X * 256);
            var g = (int)(totalDiffuse.Y * 256);
            var b = (int)(totalDiffuse.Z * 256);

            r = Math.Min(r, 255);
            g = Math.Min(g, 255);
            b = Math.Min(b, 255);

            // Set Pixel
            bitmap.SetPixel(x, y, Color.FromArgb(r, g, b));
        }
    }
    this.LightMapTextureID = Texture.loadImage(bitmap);
}

片段着色器(上述光照贴图的替代方法,创造相同的效果)

#version 330

precision highp float;

in vec2 frag_texcoord;
in vec3 toLightVector[8];

uniform sampler2D MyTexture0;
uniform vec3 LightColour[8];
uniform vec3 LightAttenuation[8];

uniform float NumberOfLights;

out vec4 finalColor;

void main(void)
{
    vec3 totalDiffuse;

    for (int i=0; i<NumberOfLights; i++) {
    {
        float distance = length(toLightVector[i]);
        float attFactor = LightAttenuation[i].x + (LightAttenuation[i].y * distance) + (LightAttenuation[i].z * distance * distance);
        vec3 diffuse = (LightColour[i]) / attFactor;
        totalDiffuse += diffuse;
    }
    finalColor = vec4(totalDiffuse, 1.0) * texture(MyTexture0, frag_texcoord)
    }
}

0 个答案:

没有答案