我的shaderToy之用shader画球(1)

在网上一搜画球能搜出大片方法,大概原理都是把求分为很多个三角形然后画出来.这段时间有空想起以前看过的shadertoy.com这个网站,一时兴起想能不能只用shader来画一个?实践了下发现代码还挺简单:

vertex Shader:

precision mediump float;
attribute vec3 position;
attribute vec2 texCoord;
uniform mat4 ModelViewMatrix;
uniform mat4 ProjectionMatrix;
mat4 u_modelViewProjectionMatrix;
varying mediump vec2 v_texCoord;
void main()
{
     u_modelViewProjectionMatrix = ProjectionMatrix * ModelViewMatrix;
    v_texCoord = texCoord;
    gl_Position = u_modelViewProjectionMatrix * vec4(position, 1.);
}

其中 u_modelViewProjectionMatrix 是单位矩阵.

然后是fragmentshader:

precision mediump float;
uniform lowp sampler2D mytexture;   //u_Sampler
uniform float u_Scale, u_Aspect;
uniform mat3 u_Transform;
uniform mat4 u_Proj;
varying mediump vec2 v_texCoord;
#define PI 3.141592653589793

void main()
{
    vec2 rads = vec2(PI * 2., PI);
    vec2 uv = (v_texCoord.xy ) * 2.0 - 1.0;     //-1.0 ~ 1.0
    uv.y *= u_Aspect; // adjust for aspect

    float rr = dot(uv, uv);
    float t = abs(1.0 - rr);    //球半径为1.0
    float z = sqrt(t);          //该点在球上的z值.
    z= -1.0 *z;
    vec3 sphere_pnt = vec3(uv.x,uv.y,z);
    float lon = atan(sphere_pnt.z,sphere_pnt.x);
    float lat = acos(sphere_pnt.y);
    vec2 norCoord = vec2(lon, lat) / rads;
    norCoord.x = 1.0 - norCoord.x;
    gl_FragColor = texture2D(mytexture, norCoord);
}

基本原理就是以屏幕位置作为一个半径为1的球的x y坐标.算出z值,得到球表面的三维坐标,再转为极坐标系,在纹理图中找到对应位置.得到最终效果:

我的shaderToy之用shader画球(1)_第1张图片

最终效果离我的理想效果有点差距. 代码中我的z值取负数,理论上贴出来的应该是球背面,也就是像上次写的这篇文章的效果OpenGL,z值转深度值计算 - 拖延症补丁.exe - 博客频道 - CSDN.NET .把z>0的称为前半球,z<0的称为后半球.实际上把z改为正数发现纹理采样确实采到后面去了.但是依然是凸起的效果.也就是始终沿着前半球表面采样.

想了好久,请教了大神也没解决, 先放博客搁置了.
我猜可能和投影矩阵有关.这样变换的程序确定是无法设置projectMatrix,也就是使用的是indentify matrix. 因为projectMatrix可能不是正定的,也没办法取逆来做.带进一步检验.

你可能感兴趣的:(GL,shader)