OpenGL ES 2.0 - 鱼眼着色器显示灰色图像

2023-11-30

我一直在尝试使用 Shadertoy 的鱼眼着色器。 我添加了自己的帧分辨率,并更改了一些关键字(texture -> texture2D, fragColor -> gl_FragColor)但就是这样。 我真的不知道为什么它不起作用以及如何调试它.. 结果我得到了一个单色的灰色图像。

这是我的片段着色器的代码:

precision mediump float;

uniform vec4 v_Color;
uniform sampler2D u_Texture;
varying vec2 v_TexCoordinate;

#define RESOLUTION_WIDTH 375.0
#define RESOLUTION_HEIGHT 211.0
#define POWER 2.0

void main() {

    vec2 fragCoord = v_TexCoordinate;
    vec2 iResolution = vec2(RESOLUTION_WIDTH, RESOLUTION_HEIGHT);

    vec2 p = fragCoord.xy / iResolution.x; // normalized coords with some cheat

    float prop = iResolution.x / iResolution.y;

    vec2 m = vec2(0.5, 0.5 / prop); // center coords
    vec2 d = p - m; // vector from center to current fragment
    float r = sqrt(dot(d, d)); // distance of pixel from center

    float power = POWER;

    float bind; // radius of 1:1 effect
    if (power > 0.0)
        bind = sqrt(dot(m, m)); // stick to corners
    else {
        if (prop < 1.0)
            bind = m.x;
        else
            bind = m.y;
    } // stick to borders

    // Weird formulas
    vec2 uv;
    if (power > 0.0) // fisheye
        uv = m + normalize(d) * tan(r * power) * bind / tan( bind * power);
    else if (power < 0.0) // antifisheye
        uv = m + normalize(d) * atan(r * -power * 10.0) * bind / atan(-power * bind * 10.0);
    else uv = p; // no effect for power = 1.0

    vec3 col = texture2D(u_Texture, vec2(uv.x, -uv.y * prop)).xyz; // Second part of cheat
    gl_FragColor = vec4(col, 1.0);
} 

这是我的原始着色器,用于显示完美运行的图像:

precision mediump float;

uniform vec4 v_Color;
uniform sampler2D u_Texture;
varying vec2 v_TexCoordinate;

void main() {
    // premultiplied alpha
    vec4 texColor = texture2D(u_Texture, v_TexCoordinate);
    // Scale the texture RGB by the vertex color
    texColor.rgb *= v_Color.rgb;
    // Scale the texture RGBA by the vertex alpha to reinstate premultiplication
    gl_FragColor = texColor * v_Color.a;
}

以下是 ShaderToy 上预期结果的链接:

ShaderToy 鱼眼

原始结果图像:

Original image

使用我的着色器:

With my shader

使用 Rabbid76 解决方案:

enter image description here

功率 = 1.1 :

enter image description here

解决方案 n2 且幂 = 10(更大的图像看得更清楚):

enter image description here

文字背后有一些背景,不用理会;)


在你的着色器代码中fragCoord假设为窗口坐标,最小值为 (0, 0),最大值为视口的宽度和高度。但在你的代码中v_TexCoordinate被分配给fragCoord. v_TexCoordinate是[0, 1]范围内的纹理corodiante。

Use gl_FragCoord代替v_TexCoordinate:

// vec2 fragCoord = v_TexCoordinate; <--- delete 
vec2 fragCoord = gl_FragCoord.xy;  
vec2 p = fragCoord.xy / iResolution.x;

或者跳过除以窗口分辨率:

vec2 fragCoord = v_TexCoordinate;  
// vec2 p = fragCoord.xy / iResolution.x; <-- delete 
vec2 p = fragCoord.xy * vec2(1.0, iResolution.y/iResolution.x); 

如果不需要调整纵横比,那么甚至可以这样做:

vec2 p = v_TexCoordinate.xy; 

请参阅 WebGL 示例,其中我使用您的原始着色器代码并应用了建议的更改:

(function loadscene() {

var gl, canvas, prog, bufObj = {};
var texture;

function render(deltaMS) {

  texture.bound = texture.bound || texture.bind( 0 );

  gl.viewport( 0, 0, vp_size[0], vp_size[1] );
  gl.enable( gl.DEPTH_TEST );
  gl.clearColor( 0.0, 0.0, 0.0, 1.0 );
  gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
  ShProg.Use( progDraw );
  ShProg.SetF2( progDraw, "resolution", vp_size );
  ShProg.SetI1( progDraw, "u_texture", 0 );
  VertexBuffer.Draw( bufRect );

  requestAnimationFrame(render);
}  

function initScene() {

  canvas = document.getElementById( "texture-canvas");
  gl = canvas.getContext( "experimental-webgl" );
  //gl = canvas.getContext( "webgl2" );
  if ( !gl )
    return;
    
  progDraw = ShProg.Create( 
    [ { source : "draw-shader-vs", stage : gl.VERTEX_SHADER },
      { source : "draw-shader-fs", stage : gl.FRAGMENT_SHADER }
    ] );
  progDraw.inPos = gl.getAttribLocation( progDraw.progObj, "inPos" );
  if ( progDraw.progObj == 0 )
      return;

  bufRect = VertexBuffer.Create(
  [ { data :  [ -1, -1, 1, -1, 1, 1, -1, 1 ], attrSize : 2, attrLoc : progDraw.inPos } ],
    [ 0, 1, 2, 0, 2, 3 ] );


  texture = new Texture( "https://raw.githubusercontent.com/Rabbid76/graphics-snippets/master/resource/texture/supermario.jpg" ); 
  texture.bound = false;

  window.onresize = resize;
  resize();
  requestAnimationFrame(render);
}

function resize() {
  //vp_size = [gl.drawingBufferWidth, gl.drawingBufferHeight];
  vp_size = [window.innerWidth, window.innerHeight]
  vp_size[0] = vp_size[1] = Math.min(vp_size[0], vp_size[1]); 
  //vp_size = [256, 256]
  canvas.width = vp_size[0];
  canvas.height = vp_size[1];
}

var ShProg = {
Create: function (shaderList) {
  var shaderObjs = [];
  for (var i_sh = 0; i_sh < shaderList.length; ++i_sh) {
      var shderObj = this.Compile(shaderList[i_sh].source, shaderList[i_sh].stage);
      if (shderObj) shaderObjs.push(shderObj);
  }
  var prog = {}
  prog.progObj = this.Link(shaderObjs)
  if (prog.progObj) {
      prog.attrInx = {};
      var noOfAttributes = gl.getProgramParameter(prog.progObj, gl.ACTIVE_ATTRIBUTES);
      for (var i_n = 0; i_n < noOfAttributes; ++i_n) {
          var name = gl.getActiveAttrib(prog.progObj, i_n).name;
          prog.attrInx[name] = gl.getAttribLocation(prog.progObj, name);
      }
      prog.uniLoc = {};
      var noOfUniforms = gl.getProgramParameter(prog.progObj, gl.ACTIVE_UNIFORMS);
      for (var i_n = 0; i_n < noOfUniforms; ++i_n) {
          var name = gl.getActiveUniform(prog.progObj, i_n).name;
          prog.uniLoc[name] = gl.getUniformLocation(prog.progObj, name);
      }
  }
  return prog;
},
AttrI: function (prog, name) { return prog.attrInx[name]; },
UniformL: function (prog, name) { return prog.uniLoc[name]; },
Use: function (prog) { gl.useProgram(prog.progObj); },
SetI1: function (prog, name, val) { if (prog.uniLoc[name]) gl.uniform1i(prog.uniLoc[name], val); },
SetF1: function (prog, name, val) { if (prog.uniLoc[name]) gl.uniform1f(prog.uniLoc[name], val); },
SetF2: function (prog, name, arr) { if (prog.uniLoc[name]) gl.uniform2fv(prog.uniLoc[name], arr); },
SetF3: function (prog, name, arr) { if (prog.uniLoc[name]) gl.uniform3fv(prog.uniLoc[name], arr); },
SetF4: function (prog, name, arr) { if (prog.uniLoc[name]) gl.uniform4fv(prog.uniLoc[name], arr); },
SetM33: function (prog, name, mat) { if (prog.uniLoc[name]) gl.uniformMatrix3fv(prog.uniLoc[name], false, mat); },
SetM44: function (prog, name, mat) { if (prog.uniLoc[name]) gl.uniformMatrix4fv(prog.uniLoc[name], false, mat); },
Compile: function (source, shaderStage) {
  var shaderScript = document.getElementById(source);
  if (shaderScript)
      source = shaderScript.text;
  var shaderObj = gl.createShader(shaderStage);
  gl.shaderSource(shaderObj, source);
  gl.compileShader(shaderObj);
  var status = gl.getShaderParameter(shaderObj, gl.COMPILE_STATUS);
  if (!status) alert(gl.getShaderInfoLog(shaderObj));
  return status ? shaderObj : null;
},
Link: function (shaderObjs) {
  var prog = gl.createProgram();
  for (var i_sh = 0; i_sh < shaderObjs.length; ++i_sh)
      gl.attachShader(prog, shaderObjs[i_sh]);
  gl.linkProgram(prog);
  status = gl.getProgramParameter(prog, gl.LINK_STATUS);
  if ( !status ) alert(gl.getProgramInfoLog(prog));
  return status ? prog : null;
} };

var VertexBuffer = {
Create: function(attribs, indices, type) {
  var buffer = { buf: [], attr: [], inx: gl.createBuffer(), inxLen: indices.length, primitive_type: type ? type : gl.TRIANGLES };
  for (var i=0; i<attribs.length; ++i) {
      buffer.buf.push(gl.createBuffer());
      buffer.attr.push({ size : attribs[i].attrSize, loc : attribs[i].attrLoc, no_of: attribs[i].data.length/attribs[i].attrSize });
      gl.bindBuffer(gl.ARRAY_BUFFER, buffer.buf[i]);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array( attribs[i].data ), gl.STATIC_DRAW);
  }
  gl.bindBuffer(gl.ARRAY_BUFFER, null);
  if ( buffer.inxLen > 0 ) {
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer.inx);
      gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( indices ), gl.STATIC_DRAW);
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
  }
  return buffer;
},
Draw: function(bufObj) {
  for (var i=0; i<bufObj.buf.length; ++i) {
      gl.bindBuffer(gl.ARRAY_BUFFER, bufObj.buf[i]);
      gl.vertexAttribPointer(bufObj.attr[i].loc, bufObj.attr[i].size, gl.FLOAT, false, 0, 0);
      gl.enableVertexAttribArray( bufObj.attr[i].loc);
  }
  if ( bufObj.inxLen > 0 ) {
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufObj.inx);
      gl.drawElements(bufObj.primitive_type, bufObj.inxLen, gl.UNSIGNED_SHORT, 0);
      gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null );
  }
  else
      gl.drawArrays(bufObj.primitive_type, 0, bufObj.attr[0].no_of );
  for (var i=0; i<bufObj.buf.length; ++i)
      gl.disableVertexAttribArray(bufObj.attr[i].loc);
  gl.bindBuffer( gl.ARRAY_BUFFER, null );
} };

class Texture {
    constructor( name, dflt ) {
        let texture = this;
        this.dflt = dflt || [128,128,128,255]
        let image = { "cx": this.dflt.w || 1, "cy": this.dflt.h || 1, "plane": this.dflt.p || this.dflt };
        this.size = [image.cx, image.cy];
        this.dummyObj = Texture.createTexture2D( image, true )
        this.image = new Image(64,64);
        this.image.setAttribute('crossorigin', 'anonymous');
        this.image.onload = function () {
            let cx = 1 << 31 - Math.clz32(texture.image.naturalWidth);
            if ( cx < texture.image.naturalWidth ) cx *= 2;
            let cy = 1 << 31 - Math.clz32(texture.image.naturalHeight);
            if ( cy < texture.image.naturalHeight ) cy *= 2;
            var canvas = document.createElement( 'canvas' );
            canvas.width  = cx;
            canvas.height = cy;
            var context = canvas.getContext( '2d' );
            context.drawImage( texture.image, 0, 0, canvas.width, canvas.height );
            texture.textureObj = Texture.createTexture2D( canvas, true );
            texture.size = [cx, cy];
        }
        this.image.src = name;
    }
    static createTexture2D( image, flipY ) {
        let t = gl.createTexture();
        gl.activeTexture( gl.TEXTURE0 );
        gl.bindTexture( gl.TEXTURE_2D, t );
        gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, flipY != undefined && flipY == true );
        if ( image.cx && image.cy && image.plane )
            gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, image.cx, image.cy, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(image.plane) );
        else
            gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image );
        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR );
        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR );
        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT );
        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT );
        gl.bindTexture( gl.TEXTURE_2D, null );
        return t;
    }
    bind( texUnit = 0 ) {
        gl.activeTexture( gl.TEXTURE0 + texUnit );
        if ( this.textureObj ) { 
            gl.bindTexture( gl.TEXTURE_2D, this.textureObj );
            return true;
        }
        gl.bindTexture( gl.TEXTURE_2D, this.dummyObj );
        return false;
    }
};

initScene();

})();
<script id="draw-shader-vs" type="x-shader/x-vertex">
precision mediump float;

attribute vec2 inPos;

void main()
{
    gl_Position = vec4( inPos.xy, 0.0, 1.0 );
}
</script>
  
<script id="draw-shader-fs" type="x-shader/x-fragment">
precision mediump float;
  
uniform vec2 resolution;

uniform sampler2D u_Texture;

#define RESOLUTION_WIDTH 375.0
#define RESOLUTION_HEIGHT 211.0
#define POWER 2.0

void main( void )
{
  vec2 fragCoord = gl_FragCoord.xy;
  vec2 iResolution = resolution; 
  //vec2 fragCoord = v_TexCoordinate;
  //vec2 iResolution = vec2(RESOLUTION_WIDTH, RESOLUTION_HEIGHT);

  vec2 p = fragCoord.xy / iResolution.x; // normalized coords with some cheat

  float prop = iResolution.x / iResolution.y;

  vec2 m = vec2(0.5, 0.5 / prop); // center coords
  vec2 d = p - m; // vector from center to current fragment
  float r = sqrt(dot(d, d)); // distance of pixel from center

  float power = POWER;

  float bind; // radius of 1:1 effect
  if (power > 0.0)
      bind = sqrt(dot(m, m)); // stick to corners
  else {
      if (prop < 1.0)
          bind = m.x;
      else
          bind = m.y;
  } // stick to borders

  // Weird formulas
  vec2 uv;
  if (power > 0.0) // fisheye
      uv = m + normalize(d) * tan(r * power) * bind / tan( bind * power);
  else if (power < 0.0) // antifisheye
      uv = m + normalize(d) * atan(r * -power * 10.0) * bind / atan(-power * bind * 10.0);
  else uv = p; // no effect for power = 1.0

  vec3 col = texture2D(u_Texture, vec2(uv.x, -uv.y * prop)).xyz; // Second part of cheat
  gl_FragColor = vec4(col, 1.0);
}

</script>

<body>
<canvas id="texture-canvas" style="border: none"></canvas>
</body>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenGL ES 2.0 - 鱼眼着色器显示灰色图像 的相关文章

  • 如何将点光源转换为卵形/椭圆形?

    我希望通过具有不同 x 和 y 值的 vec2 半径将当前的圆形光变成椭圆形 有没有办法根据我当前在片段着色器中的代码来做到这一点 uniform struct Light vec4 colour vec3 position vec2 ra
  • 使用未声明的标识符“gl_InstanceID”

    大家好 我一直在IOS平台上尝试在OpenGLES2 0中进行实例化绘制 我的渲染代码 glEnableVertexAttribArray glVertexAttribPointer glDrawElementsInstancedEXT G
  • GLSL 棋盘图案

    我想用跳棋来遮蔽四边形 f P 下限 Px 下限 Py mod2 我的四边形是 glBegin GL QUADS glVertex3f 0 0 0 0 glVertex3f 4 0 0 0 glVertex3f 4 4 0 0 glVert
  • LibGDX - 着色器适用于桌面但不适用于 Android

    我编写了一个简单的程序 可以在 3D 环境中渲染球体 并根据球体周围的四个光源为其着色 当我在桌面上运行该程序时 它工作得很好 但在 Android 设备上 球体只是纯色的 下面是一些图片来说明我正在谈论的内容 gt Desktop gt
  • 使用 OpenGL 着色器进行数学计算 (C++)

    我有一个矩阵 例如 100x100 尺寸 我需要对每个元素进行计算 matrix i j tt 8 5例如 我有一个巨大的矩阵 我想使用 OpenGL 着色器来实现该算法 我想使用着色器 例如 uniform float val unifo
  • 解决 Three.js / webGL 中的 gl_PointSize 限制

    我正在使用 Three js 创建交互式数据可视化 此可视化涉及渲染 68000 个节点 其中每个不同的节点具有不同的大小和颜色 最初我尝试通过渲染网格来实现此目的 但事实证明这非常昂贵 我当前的尝试是使用 Three js 粒子系统 每个
  • 如何将任意颜色的色度键滤镜应用到实时摄像头源ios?

    基本上我想将色度键滤镜应用到 ios 实时摄像头源 但我希望用户选择将被另一种颜色替换的颜色 我找到了一些使用绿屏的示例 但我不知道如何动态替换颜色而不仅仅是绿色 知道如何以最佳性能实现这一目标吗 您之前曾询问过我的情况GPUImage h
  • 安装 OpenGL ES 并编译 Android 代码

    我刚刚开始在 android 上学习 OpenGL ES 使用这本书 https rads stackoverflow com amzn click com 1430226471 并遇到了采用的问题source http apress co
  • OpenGL ES 2.0 中的纹理点?

    我正在尝试在 OpenGL ES 2 0 中为粒子系统实现纹理点 例如点精灵 我遇到的问题是所有点都渲染为实心黑色方块 而不是正确映射纹理 我已经验证 gl PointCoord 实际上返回从 0 0 到 1 0 的 x y 值 这将映射到
  • 使用 GLSL 直接在着色器中从位置计算平移矩阵

    我正在开发 C OpengL 程序以及 GLSL 顶点和片段着色器 我正在创建同一对象的多个实例 我只需要改变实例之间的对象位置 这是我所做的 我正在使用一个统一变量 它是一个变换矩阵数组 每个矩阵代表一个对象实例 MVP 也是一个变换矩阵
  • OpenGL:伽玛校正图像看起来不线性

    我使用 OpenGL 进行渲染 当我将线性值写入默认帧缓冲区 没有任何伽玛校正 时 它们在我的显示器上显示为线性 这违背了我认为我所知道的关于伽马校正的一切 如下所述 http gamedevelopment tutsplus com ar
  • OpenGL - 我应该存储属性/统一位置吗?

    Are glGetUniformLocation and glGetAttribLocation耗时 哪种方式更好 Call glGetAttribLocation or glGetUniformLocation每次我需要它 将位置存储在变
  • Android 中的 OpenGL 缩小

    我正在使用 3D 对象并渲染它并通过扩展 GLSurfaceView 实现渲染器来显示它 问题是如何通过捏合和捏合进行缩小 下面是我的班级 package com example objLoader import java nio Byte
  • Android 7 GraphicBuffer 替代方案,用于直接访问 OpenGL 纹理内存

    从移动设备具有 CPU 和 GPU 共享内存这一事实中获利的唯一方法是使用GrphicBuffer 但由于 Android 7 限制对私有本机库 包括 gralloc 的访问 因此无法再使用它 问题 是否有其他方法可以直接内存访问纹理的像素
  • Android OpenGL ES 支持无处不在?

    我需要了解如果我选择在 OpenGL 而不是 android graphics 中的 android 原生 2D 图形 API 进行绘图 我会损失多少潜在安装量 android 文档似乎暗示 OpenGL ES API 基本上在所有手机上都
  • 在 iOS 上使用 OpenGL ES 2.0 进行实例化绘制

    简而言之 谁能确认是否可以使用内置变量gl InstanceID or gl InstanceIDEXT 在 iOS 上使用 OpenGL ES 2 0 的顶点着色器中GL EXT draw instanced启用 Longer 我想使用绘
  • 如何将 asm 着色器编译为 fxo 文件?

    我有一个已编译的 fxo 着色器 我正在尝试对其进行稍微编辑 仅调整一些常量 使用 fxdis https code google com archive p fxdis d3d1x https code google com archiv
  • OpenGL-ES、iPhone 和间歇性错误:GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES (0x8CD6)

    我有一个在 UIView 中使用 OpenGL ES 和 EAGLContext 的应用程序 非常类似于 Apple 的 GLPaint 示例代码应用程序 我在 iPhone 4 上看到这个错误 但在 iPad 上却没有 这可能很重要 大多
  • OpenGL 使用着色器将 NV12 转换为 RGB24

    我尝试编写一个应用程序来在 OpenGL 中显示 YUV 图像 我使用此代码片段在 C 中成功将 Y UV 转换为 RGB source https blog csdn net subfate article details 4730514
  • 如何将AVFrame转换为glTexImage2D使用的纹理?

    如您所知 AVFrame 有 2 个属性 pFrame gt data pFrame gt linesize 当我从视频 sdcard test mp4 android平台 读取帧后 并将其转换为RGB AVFrame副 img conve

随机推荐