2017-02-12 4 views
2

나는 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; 
} 

렌더러 가능성이

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); 
       } 
      } 
     } 
    ... 
} 
+0

멀티 터치 이벤트를 삭제할 수 없습니까? –

+0

@UtsavShrestha 나는 할 수 있었다. 그러나 나는 원하지 않는다. 멀티 터치는 앱의 정상적인 동작의 일부이며 쉐이더는이를 처리 할 수 ​​있어야합니다. – Cody

+0

그런 경우 나는 질문을 upvote, 잘하면 쉐이더에 대한 더 많은 경험을 가진 사람이 귀하의 질문에 대답합니다. –

답변

1

문제를 해결하는 가장 쉬운 방법 대신 색상에 대한 하나의 유니폼을 필요없이 그리드 광장 당 색상을 설정하는 것입니다 . 열의 위치와 크기에 대해 이미이 작업을 수행 했으므로 쉽게 확장하여 각 열의 색을 기록 할 수 있습니다. 셰이더에서

, 당신은 배열에 ColumnGlowColor을 변경 것 (쉽게 당신의 위치와 규모 변수로, 6 개 별도의 변수를하는 것보다) :

uniform vec4 ColumnGlowColor[6];   // color of the Column 

어떻게 실제로 출력 색상이 적용하는 것입니다 빛이 실제로 계산되는 방법에 대한 코드를 표시하지 않기 때문에 말하기 어렵습니다. generateGlow 함수는 입력 위치에서 광선의 강도를 반환한다고 가정하는 것이 합리적입니다. 강도를 반환하는 대신 색상 (RGB 구성 요소) 인 float4와 알파의 강도를 반환해야합니다. 일부 드라이버가 이것에 대해 허용된다 (당신이 배열 연산자를 추가해야합니다 균일의 위치를 ​​얻을 때

gl_FragColor = fromTexture + sumOfReturnsFromGenerateGlow; 

는 올바르게 바인딩 : 그런 다음 단지에 픽셀 셰이더의 최종 라인을 바꿀 것 다른 사람, 아닙니다). 원래 이름은 stringGlowColor 이었지만, 균일 한 이름과 일치해야합니다 : 당신이 mGlowColorHandle 값을 설정하는 경우

mGlowColorHandle = GLES20.glGetUniformLocation(programHandle, "ColumnGlowColor[]"); 

, 당신은 일정에 추가 인덱스를 설정하여, 각 배열의 항목을 설정 것입니다.

GLES20.glUniform4f(mGlowColorHandle+i,.0f, .0f, 1.0f, 1.0f); 

참고 : 예를 들면, 첫 번째 열 세트에 대한 변경 것이다 출력 할 수 있습니다 여러 색상 셰이더에서, 당신은 EXT_draw_buffers GLES 확장자를 사용하는 경우. 그러나, 당신이하고 싶지 않은 것은, 여러분이 다중 프레임 버퍼를 가지고 있지 않다고 가정하기 때문입니다.

+0

저는이 쉐이더 (color-per-square) 기능을 구현하기 위해 쉐이더를 변경하는 방법에 익숙하지 않습니다. (저는 OpenGL ES를 처음 접했습니다). 몇 가지 샘플 코드를 제공해 주시겠습니까? 특정 지침을 추가하려면 – Cody

+0

을 편집하십시오. – MuertoExcobito

+0

감사합니다. generateGlow() 메소드 로직을 포함하도록 게시물을 편집했습니다. 이 방법으로 강도 값을 반환하는 것이 맞습니다. 이 메서드 내에서 반환 할 색상 값을 어떻게 결정할 수 있습니까? x 축 터치 위치를 기반으로 색상을 선택하는 if-else 블록? 난이 범위에서 화면 너비를 결정하는 방법을 잘 모르겠다. 그래서 touchPosition.x가있는 6 개의 화면 열 중에서 어느 것이 쉽게 테스트되는지를 모른다. – Cody