【问题标题】:WebGL Why does it render a grayscale texture?WebGL 为什么要渲染灰度纹理?
【发布时间】:2021-10-30 10:53:28
【问题描述】:

我在平面上渲染的纹理有问题。我将 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);
        }

【问题讨论】:

  • 纹理的像素格式为PixelFormat.LUMINANCE。 “LUMINANCE”是一个灰度值。您必须使用带有 RGB 信息的纹理格式。
  • 感谢您的回答。我选择 Luminance 是因为它是唯一有效的,因为数组没有足够的 rgb 或 rgba 结构值。意味着它是一个 bgra5551 的 ushort 数组,我将其转换为 webgl 可以处理的 argb32 int 数组。该错误意味着在将像素格式设置为 rgb 或 rgba 时需要 43 个字节和 44 个像素,而它只包含 19 行(0 像素)。

标签: c# blazor webgl .net-5


【解决方案1】:

纹理的像素格式为 PixelFormat.LUMINANCE。 “LUMINANCE”是一个灰度值。您必须使用带有 RGB 信息的纹理格式。
由于您的像素格式为 bgra5551,因此您可以使用PixelType.UNSIGNED_SHORT_5_5_5_1(参见WebGL specification - Texture objects):

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

【讨论】:

  • @3HMonkey 错误消息是 "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array"。所以buffer 显然是不是Uint16Array! (如果您有额外的信息,您需要将其添加到问题中,而不是在 cmets 中)
猜你喜欢
  • 2021-09-05
  • 1970-01-01
  • 2020-03-04
  • 1970-01-01
  • 2013-02-03
  • 1970-01-01
  • 1970-01-01
  • 2017-02-18
  • 1970-01-01
相关资源
最近更新 更多