首页 > 解决方案 > WebGL 为什么要渲染灰度纹理?

问题描述

我在飞机上渲染的纹理有问题。我将 webgl 用于 blazor 服务器应用程序,并将 net5 用于后端。

那我在做什么?

  1. 我从一个文件中读取了一个图像(这个文件包含很多图像)+ 到目前为止效果很好。我返回一个整数数组。
  2. 我用它创造了一个纹理。
  3. 我把它渲染到飞机上。

问题:它以灰度而不是颜色呈现,我不知道为什么。

在此处输入图像描述

它应该是这样的: 在此处输入图像描述

顶点着色器:

attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
uniform mat4 model;
uniform mat4 projection;
varying vec3 vNormal;
varying vec2 vUv;

void main() {
    vUv = uv;
    vNormal = (model * vec4(normal, 0.)).xyz;
    gl_Position = projection * model * vec4(position, 1.);
}

片段着色器:

#ifdef GL_ES
precision highp float;
#endif

uniform vec3 lightDirection;
uniform float ambientLight;
uniform sampler2D diffuse;
varying vec3 vNormal;
varying vec2 vUv;

void main() {
    float lightness = -clamp(dot(normalize(vNormal), normalize(lightDirection)), -1., 0.);
    lightness = ambientLight + (1. - ambientLight) * lightness;
    gl_FragColor = vec4(texture2D(diffuse, vUv).rgb * lightness, 1);
}

这是我构建的功能:

var gl = await this._canvasReference.CreateWebGLAsync(new WebGLContextAttributes
                {
                    PreserveDrawingBuffer = true,
                    PowerPreference = WebGLContextAttributes.POWER_PREFERENCE_HIGH_PERFORMANCE
                });

                await gl.ClearColorAsync(0.1f, 0.1f, 0.3f, 1);
                await gl.EnableAsync(EnableCap.DEPTH_TEST);
                await gl.ClearAsync(BufferBits.COLOR_BUFFER_BIT | BufferBits.DEPTH_BUFFER_BIT);
                await gl.EnableAsync(EnableCap.CULL_FACE);
                await gl.FrontFaceAsync(FrontFaceDirection.CCW);
                await gl.CullFaceAsync(Face.BACK);


                //Init the shaders     
                _shaderProgram = await ShaderProgram.InitShaderProgram(
                gl,
                await File.ReadAllTextAsync("includes/shaders/basic.vert"),
                await File.ReadAllTextAsync("includes/shaders/basic.frag"),
                new List<string>() { "position", "normal", "uv" },
                new List<string>() { "model", "projection", "ambientLight", "lightDirection", "diffuse" });

                // Get geometry like plane from object files
                var geometry = Geometry.ParseObjFile(await File.ReadAllTextAsync("includes/models/plane.obj"));

               
                var texbuffer = await ArtworkProvider.GetStaticAsync(0x03AB);
                _texture = await WebGLFramework.Texture.BuildLandAsync(gl, texbuffer);


                //_texture = await WebGLFramework.Texture.BuildAsync(gl, _textureContainer.GetValueOrDefault(0), size, size);
                _cylinderMesh = await Mesh.BuildAsync(gl, geometry, _texture);
                _light = new Light();
                await DrawSceneAsync();

最后是我的 BuildLandAsync 任务:

public static async Task<Texture> BuildLandAsync(WebGLContext gl, int[] buffer, int width = 44, int height = 44)
        {
            
            var texture = await gl.CreateTextureAsync();
            await gl.BindTextureAsync(TextureType.TEXTURE_2D, texture);
            await gl.TexImage2DAsync(Texture2DType.TEXTURE_2D, 0, PixelFormat.LUMINANCE, width, height, 0, PixelFormat.LUMINANCE, PixelType.UNSIGNED_BYTE, buffer);
            await gl.TexParameterAsync(TextureType.TEXTURE_2D, TextureParameter.TEXTURE_MIN_FILTER, (int)TextureParameterValue.NEAREST);
            await gl.TexParameterAsync(TextureType.TEXTURE_2D, TextureParameter.TEXTURE_MAG_FILTER, (int)TextureParameterValue.NEAREST);
            await gl.TexParameterAsync(TextureType.TEXTURE_2D, TextureParameter.TEXTURE_WRAP_S, (int)TextureParameterValue.CLAMP_TO_EDGE);
            await gl.TexParameterAsync(TextureType.TEXTURE_2D, TextureParameter.TEXTURE_WRAP_T, (int)TextureParameterValue.CLAMP_TO_EDGE);
            return new Texture(gl, texture, width, height);
        }

标签: c#blazorwebgl.net-5

解决方案


纹理的像素格式是 PixelFormat.LUMINANCE。“LUMINANCE”是一个灰度值。您必须使用带有 RGB 信息的纹理格式。
由于您的像素格式是 bgra5551,您可以使用PixelType.UNSIGNED_SHORT_5_5_5_1(请参阅WebGL 规范 - 纹理对象):

await gl.TexImage2DAsync(Texture2DType.TEXTURE_2D, 0, PixelFormat.RGBA, 
    width, height, 0, PixelFormat.RGBA, PixelType.UNSIGNED_SHORT_5_5_5_1, buffer);

推荐阅读