Opengl es glsl中偏导数的手动计算(与dFdx比较)

Opengl es glsl中偏导数的手动计算(与dFdx比较),opengl-es,glsl,shader,fragment-shader,Opengl Es,Glsl,Shader,Fragment Shader,我假设dFdx(变量)可以通过手动实现,如下例所示: #extension GL_OES_standard_derivatives : enable float circle (const vec2 st, float r) { return sin(300.0 * length(st)); } void main() { vec2 st = gl_FragCoord.xy / u_resolution.xy; st.x *= u_resolution.x / u_r

我假设dFdx(变量)可以通过手动实现,如下例所示:

#extension GL_OES_standard_derivatives : enable

float circle (const vec2 st, float r) {
    return sin(300.0 * length(st));
}

void main() {
    vec2 st = gl_FragCoord.xy / u_resolution.xy;
    st.x *= u_resolution.x / u_resolution.y;
    float dist = circle(st, 0.5);
    float df;
    df = dFdx(dist) * 100.0;
    df = (circle(st + vec2(1.0 / u_resolution.x, 0.0), 0.5) - dist) * 100.0;
    gl_FragColor = vec4(vec3(df), 1.0);
}
但是结果不同了,手动方式似乎很顺利,有人能解释一下吗

(手册)


(dFdx)

你的假设并不完全正确

是计算两个相邻片段表达式的差(偏导数)

但是不,它并不总是当前片段和行中下一个片段的差异

考虑到差异,一次计算2x2平方的碎片。在该平方中,计算“左”和“右”碎片(
dFdx
)的差值。结果是“左”片段的
dFdx
结果,以及“右”片段的invertieren结果:

有关详细规范,请参阅

要模拟此情况,您必须计算后续和前置的结果:

float dist   = circle(st, 0.5);
float dist_n = circle(st + offs_x, 0.5);
float dist_p = circle(st - offs_x, 0.5);
对于行中的偶数片段,必须计算下一个片段和当前片段表达式的差异:

df = (dist_n - dist) * 100.0; 
df = (dist - dist_p) * 100.0;  
对于行中的奇数片段,您必须计算当前片段和前一个片段的表达式之差:

df = (dist_n - dist) * 100.0; 
df = (dist - dist_p) * 100.0;  
请参见WebGL示例,该示例将左侧的
dFdx
结果与右侧的模拟结果进行比较:

(函数loadscene(){
变量gl,canvas,prog,bufObj={};
函数渲染(deltaMS){
总图视口(0,0,vp_大小[0],vp_大小[1]);
总帐启用(总帐深度测试);
gl.clearColor(0.0,0.0,0.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
ShProg.用法(progDraw);
ShProg.SetF2(程序图,“u_分辨率”,vp_尺寸);
VertexBuffer.Draw(bufRect);
请求动画帧(渲染);
}  
函数initScene(){
canvas=document.getElementById(“canvas”);
gl=canvas.getContext(“实验性webgl”);
//gl=canvas.getContext(“webgl2”);
如果(!gl)
返回null;
var standard_Derivations=gl.getExtension(“OES_standard_Derivations”);//dFdx,dFdy
if(!标准_导数)
警报(“无标准衍生产品支持(无dFdx、dFdy)”;
progDraw=ShProg.Create(
[{来源:“绘制着色器vs”,阶段:gl.VERTEX_shader},
{来源:“绘制着色器fs”,阶段:gl.FRAGMENT_shader}
] );
progDraw.inPos=gl.getAttribLocation(progDraw.progObj,“inPos”);
如果(progDraw.progObj==0)
返回;
bufRect=VertexBuffer.Create(
[{data:[-1,-1,1,-1,1,1],attrSize:2,attrLoc:progDraw.inPos}],
[ 0, 1, 2, 0, 2, 3 ] );
window.onresize=调整大小;
调整大小();
请求动画帧(渲染);
}
函数resize(){
//vp_大小=[gl.drawingBufferWidth,gl.drawingBufferHeight];
vp_size=[window.innerWidth,window.innerHeight]
vp_大小[0]=vp_大小[1]=Math.min(vp_大小[0],vp_大小[1]);
//vp_大小=[256,256]
canvas.width=vp_大小[0];
canvas.height=vp_大小[1];
}
变量ShProg={
创建:函数(着色器列表){
var shaderObjs=[];
for(变量i_sh=0;i_sh