LibGDX-着色器可在桌面上使用,但不能在Android上使用 [英] LibGDX - Shader working on Desktop but not on Android

查看:88
本文介绍了LibGDX-着色器可在桌面上使用,但不能在Android上使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个简单的程序,该程序在3d环境中渲染球体,并根据球体周围的四个光源对其进行着色. 当我在桌面上运行该程序时,它可以正常工作,但在Android设备上,球体只是纯色.

I have written a simple program that renders a sphere in a 3d environment and colores it according to four light sources around the sphere. When I run the program on the desktop it works just fine but on an Android device the sphere is just plain colored.

以下图片说明了我在说什么:

Here are images to illustrate what I am talking about:

->桌面

-> Android

-> Android

这是着色器代码:

sphere.vert

#ifdef GL_ES
    precision mediump float;
#endif

uniform mat4 u_projectionMatrix;
uniform mat3 u_normalMatrix;
uniform mat4 u_modelViewMatrix;

const int MAX_LIGHTS = 8;
uniform int u_lights_active;
uniform vec3 u_ambient;
uniform vec3 u_position[ MAX_LIGHTS ];
uniform vec3 u_diffuse[ MAX_LIGHTS ];
uniform vec3 u_att_coeffs[ MAX_LIGHTS ];

// since builtins aren't used, we use attributes as substitute
attribute vec2 a_texCoord0;
attribute vec4 a_position;
attribute vec3 a_normal;

// outputs to fragment shader
varying vec2 v_tex_coord;
varying vec4 v_color;

void main()
{
    vec3 tempColor  = u_ambient;
    vec3 ecPosition = vec3( u_modelViewMatrix * a_position );
    vec3 viewVec    = normalize( -ecPosition );
    vec3 tnorm      = normalize( u_normalMatrix * a_normal );

    for ( int i = 0; i < u_lights_active; ++i )
    {
        float dist   = length( ecPosition - u_position[i] ); // distance from light to fragment
        float att    = 1.0 / ( u_att_coeffs[i].x + u_att_coeffs[i].y*dist + u_att_coeffs[i].z*dist*dist );

        vec3 lightVec  = normalize( u_position[i] - ecPosition );
        float diffuse  = max( dot( lightVec, tnorm ), 0.0 );
        tempColor      += att * u_diffuse[i] * diffuse;
    }

    tempColor    = clamp( tempColor, 0.0, 1.0 );
    v_color      = vec4( tempColor, 0.0 );

    gl_Position  = u_projectionMatrix * vec4( ecPosition, 1.0 );
    v_tex_coord  = a_texCoord0.xy;
}

sphere.frag

#ifdef GL_ES
    precision mediump float;
#endif

uniform sampler2D u_texture;

varying vec2 v_tex_coord;
varying vec4 v_color;

void main()
{
    vec4 texColor = texture2D( u_texture, v_tex_coord );
    gl_FragColor  = texColor * v_color;
}

我真的希望你们中的一个可以向我解释我在做错什么.

I really hope that one of you guys can explain to me, what I'm doing wrong.

版本号:

LibGDX:0.9.8

LibGDX: 0.9.8

ADT:内部版本v22.0.1-685705

ADT: Build v22.0.1-685705

Android设备:Sony Xperia S,Android 4.1.2

Android Device: Sony Xperia S, Android 4.1.2

项目构建目标:Android 4.3,API 18

Project Build Target: Android 4.3, API 18

主要内容

<uses-feature android:glEsVersion="0x00020000" android:required="true" />

着色器的创建者:

shaderProgram = new ShaderProgram( Gdx.files.internal( "shaders/sphere.vert" ), Gdx.files.internal( "shaders/sphere.frag" ) );
if ( !shaderProgram.isCompiled() )
{
    Gdx.app.error( TAG, shaderProgram.getLog() );
}

球体是一个StillModel:

创建:

final ModelLoaderHints hint = new ModelLoaderHints( true );
model = ModelLoaderRegistry.loadStillModel( Gdx.files.internal( "data/sphere.obj" ), hint );
texture = new Texture( Gdx.files.internal( "data/sphere_tex.png" ), Format.RGB888, false );
material = new Material( "mat", new TextureAttribute( texture, 0, "u_texture" ) );

渲染:

shaderProgram.begin();
texture.bind( 0 );

shaderProgram.setUniformMatrix( C.U_PROJECTION_MATRIX, cam.projection );
// light values
shaderProgram.setUniformi( C.U_LIGHTS_ACTIVE, lightsActive );
shaderProgram.setUniform3fv( C.U_LIGHT_AMBIENT, lightAmbient, 0, 3 );
shaderProgram.setUniform3fv( C.U_LIGHT_POSITION, lightPosition, 0, 3 * lightsActive );
shaderProgram.setUniform3fv( C.U_LIGHT_DIFFUSE, lightDiffuse, 0, 3 * lightsActive );
shaderProgram.setUniform3fv( C.U_LIGHT_ATT_COEFFS, lightAttCoeffs, 0, 3 * lightsActive );

modelMatrix.setToTranslation( positionWrap );
modelMatrix.rotate( rotationAxis, rotation );
modelMatrix.scale( scaleX, scaleY, scaleZ );

modelViewMatrix.set( cam.view ).mul( modelMatrix );
normalMatrix.set( modelViewMatrix ).inv().tra();

shaderProgram.setUniformMatrix( C.U_NORMAL_MATRIX, normalMatrix3x3.set( normalMatrix ) );
shaderProgram.setUniformMatrix( C.U_MODEL_VIEW_MATRIX, modelViewMatrix );

stillModel.render( shaderProgram );

shaderProgram.end();

希望这是所有需要的信息.

Hope this is all the information needed.

提前谢谢!

推荐答案

将我的基于猜测的评论转换为答案:

Converting my comment-as-guess into an answer:

GLSL规范仅要求支持非常简单的循环(非常恒定"的循环边界等).见我的答案

The GLSL spec only requires that very simple loops are supported (very "constant" loop bounds, etc). See my answer for-loop in shader code working with hardcoded number but not with uniform variable

在您的情况下,您可以通过始终循环MAX_LIGHTS并仅将无效照明的影响乘以0(或确保无效照明设置全部为零或全部为1.0或使它们变为零)来解决此问题无效).

In your case, you can probably fix this by always looping over the MAX_LIGHTS, and just multiplying the non-active light's impact by 0 (or making sure the non-active lights settings are all zero or all 1.0 or whatever makes them ineffectual).

请注意,由于像素着色器的运行方式(在SIMD并行执行中),在循环内部添加分支以跳过"不必要的工作可能会较慢.尝试使所有像素始终执行相同的指令序列.

Note that adding a branch inside the loop to "skip" unnecessary work may be slower because of how pixel shaders run (in SIMD parallel execution). Try and make all pixels always run the same sequence of instructions.

这篇关于LibGDX-着色器可在桌面上使用,但不能在Android上使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆