У меня есть приложение Android OpenGL ES, и я хочу найти способ сделать несколько разделов экрана свечением разных цветов одновременно. Само приложение делит экран на 6 столбцов, и этот столбец подсвечивается с уникальным цветом, когда пользователь прикасается к нему.OpenGL ES 2.0: Как реализовать одновременный многоцветный gl_FragColor?
Проблема, с которой я сталкиваюсь, заключается в том, что когда пользователь многократно затрагивает экран, столбцы все светятся одинаковым цветом, а не их уникальными цветами. Причиной является то, что моя логика визуализации перезаписывает gl_FragColor каждый раз, когда сенсор обнаруживается в столбце. Поскольку все столбцы используют один и тот же шейдер, все столбцы светятся как самый последний заданный цвет во время ситуаций с несколькими касаниями.
Как добиться того, чтобы каждый столбец светился уникальным цветом при касании, когда пользователь прикасается к нескольким столбцам за раз? Поскольку gl_FragColor является автоматически сгенерированной переменной, я не уверен, как добавить больше gl_FragColors, предполагая, что это поможет решить проблему.
fragment_shader
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;
}
Renderer
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);
}
}
}
...
}
Вы не можете отказаться от событий с несколькими касаниями? –
@UtsavShrestha Я мог, но я этого не хочу. Multi-touch является частью обычного поведения приложения, и шейдер должен уметь это обрабатывать. – Cody
В этом случае я рассмотрю вопрос, надеюсь, кто-то с большим опытом работы с шейдерами ответит на ваш вопрос. –