Android OpenGL ES 2.0:如何实现同步多色gl_FragColor?

Android OpenGL ES 2.0:如何实现同步多色gl_FragColor?,android,opengl-es,shader,fragment-shader,Android,Opengl Es,Shader,Fragment Shader,我有一个OpenGL ES Android应用程序,我想找到一种方法使屏幕的多个部分同时以不同的颜色发光。该应用程序本身将屏幕分为6列,当用户触摸该列时,该列将以独特的颜色点亮 我遇到的问题是,当用户多次触摸屏幕时,所有列都会发出相同的颜色,而不是它们唯一的颜色。原因是每次在列中检测到触摸时,我的渲染器逻辑都会覆盖gl_FragColor。由于所有列都使用相同的着色器,因此在多点触摸情况下,所有列都会作为最近设置的颜色发光 当用户一次触摸多个列时,如何使每一列在触摸时都发出独特的颜色?由于gl_

我有一个OpenGL ES Android应用程序,我想找到一种方法使屏幕的多个部分同时以不同的颜色发光。该应用程序本身将屏幕分为6列,当用户触摸该列时,该列将以独特的颜色点亮

我遇到的问题是,当用户多次触摸屏幕时,所有列都会发出相同的颜色,而不是它们唯一的颜色。原因是每次在列中检测到触摸时,我的渲染器逻辑都会覆盖gl_FragColor。由于所有列都使用相同的着色器,因此在多点触摸情况下,所有列都会作为最近设置的颜色发光

当用户一次触摸多个列时,如何使每一列在触摸时都发出独特的颜色?由于gl_FragColor是一个自动生成的变量,我不确定如何添加更多gl_FragColor,假设这有助于解决问题

片段着色器

precision mediump float;         // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
uniform sampler2D u_Texture;              // The input texture.

varying vec2 v_TexCoordinate;  // Interpolated texture coordinate per fragment.
varying vec3 v_Position;            // Interpolated position for this fragment.
varying vec4 v_Color;            // This is the color from the vertex shader interpolated across the triangle per fragment.
varying vec3 v_Normal;           // Interpolated normal for this fragment.

uniform vec4 ColumnGlowColor;          // color of the Column

uniform vec2 eColumnGlowPosition;   // where the Column is
uniform float eColumnGlowSizeScale; // the size to scale the glow
uniform vec2 aColumnGlowPosition;
uniform float aColumnGlowSizeScale;
uniform vec2 dColumnGlowPosition;
uniform float dColumnGlowSizeScale;
uniform vec2 gColumnGlowPosition;
uniform float gColumnGlowSizeScale;
uniform vec2 bColumnGlowPosition;
uniform float bColumnGlowSizeScale;
uniform vec2 eeColumnGlowPosition;
uniform float eeColumnGlowSizeScale;

float generateGlow( vec2 pixelPosition, float ColumnGlowScale, vec2 touchPosition){
if(stringGlowScale == 0.0) {
    return 0.0;
}
else if (touchPosition.y > pixelPosition.y){
    highp float distance = length(touchPosition-pixelPosition);  // the horizontal distance from the current pixel and the light source
    highp float threshold = .5*stringGlowScale;                             //defines the effect width
    highp float effectScale = sin((max(threshold-distance, .0))/threshold); // using sin function smooth the effect
    return effectScale;
}
else{
    highp float distance = abs(touchPosition.x-pixelPosition.x);  // the horizontal distance from the current pixel and the light source
    highp float threshold = .5*stringGlowScale;                             //defines the effect width
    highp float effectScale = sin((max(threshold-distance, .0))/threshold); // using sin function smooth the effect
    return effectScale;
}
}

// The entry point for our fragment shader.
void main(){
    highp float effectScale = 0.0;
    effectScale += generateGlow(v_Position.xy, eColumnGlowSizeScale, eColumnGlowPosition);
    effectScale += generateGlow(v_Position.xy, aColumnGlowSizeScale, aColumnGlowPosition);
    effectScale += generateGlow(v_Position.xy, dColumnGlowSizeScale, dColumnGlowPosition);
    effectScale += generateGlow(v_Position.xy, gColumnGlowSizeScale, gColumnGlowPosition);
    effectScale += generateGlow(v_Position.xy, bColumnGlowSizeScale, bColumnGlowPosition);
    effectScale += generateGlow(v_Position.xy, eeColumnGlowSizeScale, eeColumnGlowPosition);

    lowp vec4 fromTexture = texture2D(u_Texture, v_TexCoordinate);

    gl_FragColor = fromTexture + ColumnGlowColor*effectScale; 
}
 public class OpenGL_GLRenderer implements GLSurfaceView.Renderer {
     ...

     private void setUniforms(int programHandle){
            ...
            mGlowColorHandle = GLES20.glGetUniformLocation(programHandle, "stringGlowColor");           //glow color
            mStringID = GLES20.glGetUniformLocation(programHandle, "stringNum");
            mGlowPosHandles[0] = GLES20.glGetUniformLocation(programHandle, "eStringGlowPosition");      //glow effect position on neck
            mGlowScaleHandles[0] = GLES20.glGetUniformLocation(programHandle, "eStringGlowSizeScale");   //glow effect strength
            mGlowPosHandles[1] = GLES20.glGetUniformLocation(programHandle, "aStringGlowPosition");
            mGlowScaleHandles[1] = GLES20.glGetUniformLocation(programHandle, "aStringGlowSizeScale");
            mGlowPosHandles[2] = GLES20.glGetUniformLocation(programHandle, "dStringGlowPosition");
            mGlowScaleHandles[2] = GLES20.glGetUniformLocation(programHandle, "dStringGlowSizeScale");
            mGlowPosHandles[3] = GLES20.glGetUniformLocation(programHandle, "gStringGlowPosition");
            mGlowScaleHandles[3] = GLES20.glGetUniformLocation(programHandle, "gStringGlowSizeScale");
            mGlowPosHandles[4] = GLES20.glGetUniformLocation(programHandle, "bStringGlowPosition");
            mGlowScaleHandles[4] = GLES20.glGetUniformLocation(programHandle, "bStringGlowSizeScale");
            mGlowPosHandles[5] = GLES20.glGetUniformLocation(programHandle, "eeStringGlowPosition");
            mGlowScaleHandles[5] = GLES20.glGetUniformLocation(programHandle, "eeStringGlowSizeScale");

            //************************Column Glow code*******************************
            //if user's touching the screen, make nearest string glow
            for (int i = 0; i< 6; i++) {
                if (stringGlowEffects[i] != null) {
                    float top = orthoTop + (orthoBottom-orthoTop)*stringGlowEffects[i].y + scroller.getCurrentValue();
                    GLES20.glUniform2f(mGlowPosHandles[i], stringGlowEffects[i].x, top);
                    float glowEffectScale = 1.0f + (50.0f) / 300.0f;
                    GLES20.glUniform1f(mGlowScaleHandles[i], glowEffectScale);      //TODO: allow multiple colors simultaneously
                    switch (i){
                        case 0:
                            GLES20.glUniform4f(mGlowColorHandle,.0f, .0f, 1.0f, 1.0f);
                            break;
                        case 1:
                            GLES20.glUniform4f(mGlowColorHandle,.0f, 1.0f, .0f, 1.0f);
                            break;
                        case 2:
                            GLES20.glUniform4f(mGlowColorHandle,1.0f, .0f, .0f, 1.0f);
                            break;
                        case 3:
                            GLES20.glUniform4f(mGlowColorHandle,.0f, 1.0f, 1.0f, 1.0f);
                            break;
                        case 4:
                            GLES20.glUniform4f(mGlowColorHandle,1.0f, 1.0f, .0f, 1.0f);
                            break;
                        case 5:
                            GLES20.glUniform4f(mGlowColorHandle,1.0f, .0f, 1.0f, 1.0f);
                            break;
                    }
                }
                else{
                    GLES20.glUniform1f(mGlowScaleHandles[i], 0.0f);
                }
            }
        }
    ...
 }
渲染器

precision mediump float;         // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
uniform sampler2D u_Texture;              // The input texture.

varying vec2 v_TexCoordinate;  // Interpolated texture coordinate per fragment.
varying vec3 v_Position;            // Interpolated position for this fragment.
varying vec4 v_Color;            // This is the color from the vertex shader interpolated across the triangle per fragment.
varying vec3 v_Normal;           // Interpolated normal for this fragment.

uniform vec4 ColumnGlowColor;          // color of the Column

uniform vec2 eColumnGlowPosition;   // where the Column is
uniform float eColumnGlowSizeScale; // the size to scale the glow
uniform vec2 aColumnGlowPosition;
uniform float aColumnGlowSizeScale;
uniform vec2 dColumnGlowPosition;
uniform float dColumnGlowSizeScale;
uniform vec2 gColumnGlowPosition;
uniform float gColumnGlowSizeScale;
uniform vec2 bColumnGlowPosition;
uniform float bColumnGlowSizeScale;
uniform vec2 eeColumnGlowPosition;
uniform float eeColumnGlowSizeScale;

float generateGlow( vec2 pixelPosition, float ColumnGlowScale, vec2 touchPosition){
if(stringGlowScale == 0.0) {
    return 0.0;
}
else if (touchPosition.y > pixelPosition.y){
    highp float distance = length(touchPosition-pixelPosition);  // the horizontal distance from the current pixel and the light source
    highp float threshold = .5*stringGlowScale;                             //defines the effect width
    highp float effectScale = sin((max(threshold-distance, .0))/threshold); // using sin function smooth the effect
    return effectScale;
}
else{
    highp float distance = abs(touchPosition.x-pixelPosition.x);  // the horizontal distance from the current pixel and the light source
    highp float threshold = .5*stringGlowScale;                             //defines the effect width
    highp float effectScale = sin((max(threshold-distance, .0))/threshold); // using sin function smooth the effect
    return effectScale;
}
}

// The entry point for our fragment shader.
void main(){
    highp float effectScale = 0.0;
    effectScale += generateGlow(v_Position.xy, eColumnGlowSizeScale, eColumnGlowPosition);
    effectScale += generateGlow(v_Position.xy, aColumnGlowSizeScale, aColumnGlowPosition);
    effectScale += generateGlow(v_Position.xy, dColumnGlowSizeScale, dColumnGlowPosition);
    effectScale += generateGlow(v_Position.xy, gColumnGlowSizeScale, gColumnGlowPosition);
    effectScale += generateGlow(v_Position.xy, bColumnGlowSizeScale, bColumnGlowPosition);
    effectScale += generateGlow(v_Position.xy, eeColumnGlowSizeScale, eeColumnGlowPosition);

    lowp vec4 fromTexture = texture2D(u_Texture, v_TexCoordinate);

    gl_FragColor = fromTexture + ColumnGlowColor*effectScale; 
}
 public class OpenGL_GLRenderer implements GLSurfaceView.Renderer {
     ...

     private void setUniforms(int programHandle){
            ...
            mGlowColorHandle = GLES20.glGetUniformLocation(programHandle, "stringGlowColor");           //glow color
            mStringID = GLES20.glGetUniformLocation(programHandle, "stringNum");
            mGlowPosHandles[0] = GLES20.glGetUniformLocation(programHandle, "eStringGlowPosition");      //glow effect position on neck
            mGlowScaleHandles[0] = GLES20.glGetUniformLocation(programHandle, "eStringGlowSizeScale");   //glow effect strength
            mGlowPosHandles[1] = GLES20.glGetUniformLocation(programHandle, "aStringGlowPosition");
            mGlowScaleHandles[1] = GLES20.glGetUniformLocation(programHandle, "aStringGlowSizeScale");
            mGlowPosHandles[2] = GLES20.glGetUniformLocation(programHandle, "dStringGlowPosition");
            mGlowScaleHandles[2] = GLES20.glGetUniformLocation(programHandle, "dStringGlowSizeScale");
            mGlowPosHandles[3] = GLES20.glGetUniformLocation(programHandle, "gStringGlowPosition");
            mGlowScaleHandles[3] = GLES20.glGetUniformLocation(programHandle, "gStringGlowSizeScale");
            mGlowPosHandles[4] = GLES20.glGetUniformLocation(programHandle, "bStringGlowPosition");
            mGlowScaleHandles[4] = GLES20.glGetUniformLocation(programHandle, "bStringGlowSizeScale");
            mGlowPosHandles[5] = GLES20.glGetUniformLocation(programHandle, "eeStringGlowPosition");
            mGlowScaleHandles[5] = GLES20.glGetUniformLocation(programHandle, "eeStringGlowSizeScale");

            //************************Column Glow code*******************************
            //if user's touching the screen, make nearest string glow
            for (int i = 0; i< 6; i++) {
                if (stringGlowEffects[i] != null) {
                    float top = orthoTop + (orthoBottom-orthoTop)*stringGlowEffects[i].y + scroller.getCurrentValue();
                    GLES20.glUniform2f(mGlowPosHandles[i], stringGlowEffects[i].x, top);
                    float glowEffectScale = 1.0f + (50.0f) / 300.0f;
                    GLES20.glUniform1f(mGlowScaleHandles[i], glowEffectScale);      //TODO: allow multiple colors simultaneously
                    switch (i){
                        case 0:
                            GLES20.glUniform4f(mGlowColorHandle,.0f, .0f, 1.0f, 1.0f);
                            break;
                        case 1:
                            GLES20.glUniform4f(mGlowColorHandle,.0f, 1.0f, .0f, 1.0f);
                            break;
                        case 2:
                            GLES20.glUniform4f(mGlowColorHandle,1.0f, .0f, .0f, 1.0f);
                            break;
                        case 3:
                            GLES20.glUniform4f(mGlowColorHandle,.0f, 1.0f, 1.0f, 1.0f);
                            break;
                        case 4:
                            GLES20.glUniform4f(mGlowColorHandle,1.0f, 1.0f, .0f, 1.0f);
                            break;
                        case 5:
                            GLES20.glUniform4f(mGlowColorHandle,1.0f, .0f, 1.0f, 1.0f);
                            break;
                    }
                }
                else{
                    GLES20.glUniform1f(mGlowScaleHandles[i], 0.0f);
                }
            }
        }
    ...
 }
public类OpenGL\u GLRenderer实现GLSurfaceView.Renderer{
...
私有无效设置(int程序句柄){
...
mGlowColorHandle=GLES20.glGetUniformLocation(programHandle,“stringGlowColor”);//发光颜色
mStringID=GLES20.glGetUniformLocation(programHandle,“stringNum”);
mGlowPosHandles[0]=GLES20.glGetUniformLocation(programHandle,“eStringGlowPosition”);//颈部的辉光效果位置
mGlowScaleHandles[0]=GLES20.glGetUniformLocation(programHandle,“eStringGlowSizeScale”);//辉光效果强度
mGlowPosHandles[1]=GLES20.glGetUniformLocation(programHandle,“aStringGlowPosition”);
mglowscaleehandles[1]=GLES20.glGetUniformLocation(programHandle,“aStringGlowSizeScale”);
mGlowPosHandles[2]=GLES20.glGetUniformLocation(programHandle,“dStringGlowPosition”);
mglowscaleehandles[2]=GLES20.glGetUniformLocation(programHandle,“dStringGlowSizeScale”);
mGlowPosHandles[3]=GLES20.glGetUniformLocation(programHandle,“gstringLowPosition”);
mGlowScaleHandles[3]=GLES20.glGetUniformLocation(programHandle,“gstringlowsizeScale”);
mGlowPosHandles[4]=GLES20.glGetUniformLocation(programHandle,“bStringGlowPosition”);
mglowscaleehandles[4]=GLES20.glGetUniformLocation(程序句柄,“bStringGlowSizeScale”);
mGlowPosHandles[5]=GLES20.glGetUniformLocation(programHandle,“eeStringGlowPosition”);
mglowscaleehandles[5]=GLES20.glGetUniformLocation(programHandle,“eeStringGlowSizeScale”);
//************************柱辉光代码*******************************
//如果用户触摸屏幕,则使最近的字符串发光
对于(int i=0;i<6;i++){
if(stringGlowEffects[i]!=null){
浮动顶部=正交顶部+(正交底部正交顶部)*stringGlowEffects[i].y+滚动条.getCurrentValue();
GLES20.glUniform2f(mGlowPosHandles[i],stringGlowEffects[i].x,顶部);
浮标=1.0f+(50.0f)/300.0f;
GLES20.glUniform1f(mGlowScaleHandles[i],glowEffectScale);//TODO:允许同时使用多种颜色
开关(一){
案例0:
GLES20.glUniform4f(mGlowColorHandle,.0f,.0f,1.0f,1.0f);
打破
案例1:
GLES20.glUniform4f(mGlowColorHandle,.0f,1.0f,.0f,1.0f);
打破
案例2:
GLES20.glUniform4f(mGlowColorHandle,1.0f、.0f、.0f、1.0f);
打破
案例3:
GLES20.glUniform4f(mGlowColorHandle,.0f,1.0f,1.0f,1.0f);
打破
案例4:
GLES20.glUniform4f(mGlowColorHandle,1.0f,1.0f,.0f,1.0f);
打破
案例5:
GLES20.glUniform4f(mGlowColorHandle,1.0f、.0f、1.0f、1.0f);
打破
}
}
否则{
GLES20.glUniform1f(mGlowScaleHandles[i],0.0f);
}
}
}
...
}

解决问题的最简单方法可能是设置每个网格正方形的颜色,而不是为颜色设置单一的统一颜色。您已经对列的位置和大小执行了此操作,您可以轻松地扩展此操作以记录每个列的颜色

在着色器中,您可以将
ColumnGlowColor
更改为数组(比使用6个单独的变量更容易,就像使用位置和比例变量一样):

如何将其实际应用于输出颜色很难说,因为您没有显示有关如何实际计算光晕的代码。假设
generateGlow
函数返回输入位置的辉光强度似乎是合理的。不是返回强度,而是让它返回float4,即颜色(在RGB组件中)和强度(在alpha中)。然后将像素着色器的最后一行更改为:

gl_FragColor = fromTexture + sumOfReturnsFromGenerateGlow; 
当您获得制服的位置时,可能需要添加数组操作符以正确绑定它(一些驱动程序对此是允许的,其他驱动程序则不允许)。您的原始名称是
stringGlowColor
,但应与统一名称匹配:

mGlowColorHandle = GLES20.glGetUniformLocation(programHandle, "ColumnGlowColor[]");
在设置
mGlowColorHandle
值时,可以通过设置将索引添加到制服来设置每个数组项。例如,对于第一列,集合将更改为:

GLES20.glUniform4f(mGlowColorHandle+i,.0f, .0f, 1.0f, 1.0f);
注意:如果使用GLES扩展,则可以从着色器输出多种颜色。然而,这不是你想做的,因为我是阿萨姆