GLSL - 着色器无法使用mediump精度

时间:2017-10-29 13:57:58

标签: android opengl-es libgdx glsl

我有一个通过互联网找到的大气散射着色器。实际上,这是WebGL(three.js)着色器。我尝试在移动设备上运行它。我发现当我使用Qualcomm精度时,它在KIRINhihgp芯片组上效果很好,并且根本不在Mali芯片组上工作(只是黑屏) 。 Athouth,它编译没有任何错误。我认为这是因为Mali GPU(或类似的)对此着色器的精度不够highp。如果我使用mediump精度,它不适用于所有设备(只是黑屏)。是否可以使用mediump精度使这个(任何)着色器工作?或者如何使这个着色器适用于所有流行的芯片组?

顶点着色器:

attribute vec3 a_position;
attribute vec2 a_texCoord0;\n"+         

uniform mat4 u_worldTrans;
uniform mat4 u_projTrans;

varying vec3 vWorldPosition;

void main() {               
  vec4 worldPosition = u_worldTrans * vec4( a_position, 1.0 );
  vWorldPosition = worldPosition.xyz;
  gl_Position = u_projTrans * worldPosition;
}

片段着色器:

#ifdef GL_ES
precision highp float;  
#endif 

uniform vec3 sunPosition;

varying vec3 vWorldPosition;

const float turbidity = 3.2; 
const float reileigh = 2.7; 
const float luminance = 1.0; 
const float mieCoefficient = 0.007; 
const float mieDirectionalG = .990; 

#define e 2.718281828459 
#define pi 3.141592653589 

#define n 1.0003

#define pn 0.035

const vec3 lambda = vec3(0.00000068, 0.00000055, 0.00000045); 

const vec3 K = vec3(0.686, 0.678, 0.666); 

const vec3 up = vec3(0.0, 1.0, 0.0); 

#define v 4.0 

#define rayleighZenithLength 8400.0 
#define mieZenithLength 1250.0 

#define EE 1000.0 
#define sunAngularDiameterCos 0.999956676946 

#define cutoffAngle pi/1.95 
#define steepness 1.5 


vec3 simplifiedRayleigh()
{
    return 0.0005 / vec3(94., 40., 18.);
}

float rayleighPhase(float cosTheta)
{    
    return (3.0 / (16.0*pi)) * (1.0 + pow(cosTheta, 2.0));          
}

vec3 totalMie(vec3 lambda, vec3 K, float T)
{
    float val = 10E-18; 
    float c = (0.2 * T ) * val;
    return 0.434 * c * pi * pow((2.0 * pi) / lambda, vec3(v - 2.0)) * K;
}

float hgPhase(float cosTheta, float g)
{           
    return (1.0 / (4.0*pi)) * ((1.0 - pow(g, 2.0)) / pow(abs(1.0 - 2.0*g*cosTheta + pow(g, 2.0)), 1.5));
}

float sunIntensity(float zenithAngleCos)
{
    return EE * max(0.0, 1.0 - exp(-((cutoffAngle - acos(zenithAngleCos))/steepness)));
}


#define A 0.15
#define B 0.50 
#define C 0.10 
#define D 0.20 
#define E 0.02 
#define F 0.30 
#define W 1000.0 
vec3 Uncharted2Tonemap(vec3 x)
{
   return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
}

void main() 
{

    vec3 cameraPos = vec3(0., 0., -500.);
    float sunfade = 1.0-clamp(1.0-exp((sunPosition.y/4000.0)),0.0,1.0);

    float reileighCoefficient = reileigh - (1.0* (1.0-sunfade));
    vec3 sunDirection = normalize(sunPosition);

    float sunE = sunIntensity(dot(sunDirection, up));

    vec3 betaR = simplifiedRayleigh() * reileighCoefficient;

    vec3 betaM = totalMie(lambda, K, turbidity) * mieCoefficient;

    float zenithAngle = acos(max(0.0, dot(up, normalize(vWorldPosition - cameraPos))));
    float sR = rayleighZenithLength / (cos(zenithAngle) + 0.15 * pow(abs(93.885 - ((zenithAngle * 180.0) / pi)), -1.253));
    float sM = mieZenithLength / (cos(zenithAngle) + 0.15 * pow(abs(93.885 - ((zenithAngle * 180.0) / pi)), -1.253));

    vec3 Fex = exp(-(betaR * sR + betaM * sM));

    float cosTheta = dot(normalize(vWorldPosition - cameraPos), sunDirection);

    float rPhase = rayleighPhase(cosTheta*0.5+0.5);
    vec3 betaRTheta = betaR * rPhase;

    float mPhase = hgPhase(cosTheta, mieDirectionalG);
    vec3 betaMTheta = betaM * mPhase;


    vec3 Lin = pow(abs(sunE * ((betaRTheta + betaMTheta) / (betaR + betaM)) * (1.0 - Fex)),vec3(1.5));
    Lin *= mix(vec3(1.0),pow(sunE * ((betaRTheta + betaMTheta) / (betaR + betaM)) * Fex,vec3(1.0/2.0)),clamp(pow(1.0-dot(up,sunDirection),5.0),0.0,1.0));

    vec3 L0 = vec3(0.1) * Fex;

    float sundisk = smoothstep(sunAngularDiameterCos,sunAngularDiameterCos+0.00002,cosTheta);

    L0 += (sunE * 19000.0 * Fex)*sundisk;

    vec3 whiteScale = 1.0/Uncharted2Tonemap(vec3(W));

    vec3 texColor = (Lin+L0);   
    texColor *= 0.04 ;
    texColor += vec3(0.0,0.001,0.0025)*0.3;

    vec3 curr = Uncharted2Tonemap((log2(2.0/pow(luminance,4.0)))*texColor);
    vec3 color = curr*whiteScale;

    vec3 retColor = pow(color,vec3(1.0/(1.2+(1.2*sunfade))));

    gl_FragColor.rgb = retColor;

    gl_FragColor.a = 1.0;
}

我使用的是LibGDX,所以我的着色器类如下:

public class SkyShader implements Shader{

ShaderProgram program;
Camera specCamera;
int WIDTH, HEIGHT;

int u_projTrans;
int u_worldTrans;

int u_sunPosition;
int u_res;

int u_luminance;
int u_turbidity;
int u_reileigh;
int u_mieCoefficient;
int u_mieDirectionalG;

public Vector3 sunDirection = new Vector3();

Matrix4 viewInvTraMatrix = new Matrix4();


@Override
public void init() {

    program = new ShaderProgram(vert, frag);    
    if (!program.isCompiled())throw new RuntimeException(program.getLog());

    else Gdx.app.log("sky program", "shader compiled successfully!");


    u_projTrans = program.getUniformLocation("u_projTrans");
    u_worldTrans = program.getUniformLocation("u_worldTrans");

    u_sunPosition = program.getUniformLocation("sunPosition");

    u_res = program.getUniformLocation("u_res");
}   



@Override
public void dispose() {
    if(program!=null){
        program.dispose();
        program = null;
    }
}

static final float delta = 0.0028526667f;

Matrix4 projectionMatrix = new Matrix4();

@Override
public void begin(Camera camera, RenderContext context) {               
    program.begin();

    projectionMatrix.set(camera.projection);        
    if(Settings.landscape)
        projectionMatrix.rotate(0, 1, 0, (Settings.EarthRotation-100) * .4f);       
    else projectionMatrix.rotate(0, 1, 0, (Settings.EarthRotation-100) * .7f);              
    program.setUniformMatrix(u_projTrans, projectionMatrix);        

    if(Settings.EnableSlightShadowGradient)
        program.setUniformf(u_res, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());


    float rotation = Settings.EarthRotation * delta -.0375f;//- .00674f;
    float azimuth = rotation; //_azimuth;


    float inclination = .3f; //skyParams[i][4];
    float theta = (float) (Math.PI * ( inclination - 0.5f ));
    float phi = (float) (2f * Math.PI * ( azimuth - 0.5f ));

    float distance = 4000;//400000;
    sunDirection.x = (float) (distance * Math.cos( phi ));
    sunDirection.y = (float) (distance * Math.sin( phi ) * Math.sin( theta ));
    sunDirection.z = (float) (distance * Math.sin( phi ) * Math.cos( theta ));


    context.setDepthTest(GL20.GL_LEQUAL);   
    context.setCullFace(GL20.GL_FRONT);     
}


@Override
public boolean canRender(Renderable arg0) {
    return true;
}

@Override
public int compareTo(Shader arg0) {     
    return 0;
}

@Override
public void end() {
    program.end();      
}



@Override
public void render(Renderable renderable) {     
    program.setUniformMatrix(u_worldTrans, renderable.worldTransform);

    program.setUniformf(u_sunPosition, sunDirection);

    renderable.mesh.render(program, renderable.primitiveType, 
            renderable.meshPartOffset, renderable.meshPartSize);
}

}

最后,我使用以下代码渲染它:

modelBatch.begin(cam);  
modelBatch.render(sphere, skyShader);
modelBatch.end();

球体在哪里:

public ModelInstance createSphere() {
    ModelBuilder modelBuilder = new ModelBuilder();

    float radius = 4500;//450000;

    Model tempSphere;
    tempSphere = modelBuilder.createSphere(radius, radius, radius, 32, 8,
            new Material(),
            VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal | VertexAttributes.Usage.TextureCoordinates
    );

    return new ModelInstance(tempSphere,0,0,0);       
}

原始着色器为here

修改 如果我在浏览器中的problem设备上运行原始着色器(链接在上面),它可以完美运行!

提前致谢。

0 个答案:

没有答案