[英]Combine multiple shaders in OpenGLES
我有一個接收YUV通道的代碼,並使用OpenGLES繪制它們。 基本上,我有一個將它們組合在一起的着色器。
我想向結果添加銳化過濾器(使用以下示例: http : //igortrindade.wordpress.com/2010/04/23/fun-with-opengl-and-shaders/ )
我不確定如何在實際結果上運行另一個着色器(因為我想在我以前的着色器將所有通道合並到一個幀之后運行它)。
我當前的代碼如下所示:
glUniform1i(texLum, 0);
glUniform1i(texU, 1);
glUniform1i(texV, 2);
glEnableVertexAttribArray(positionLoc);
glVertexAttribPointer(positionLoc,
4,
GL_FLOAT,
GL_FALSE,
0,
&vertices[0]);
glEnableVertexAttribArray(texCoordLoc);
glVertexAttribPointer(texCoordLoc,
2,
GL_FLOAT,
GL_FALSE,
0,
&texCoords[0]);
glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(indices[0]), GL_UNSIGNED_BYTE, &indices[0]);
我想我需要在最后一行(glDrawElements)之前添加新的着色器,但是我不確定如何調用它。
我的着色器如下所示:
static char const *frag =
"uniform lowp sampler2D texLum; \n"
"uniform lowp sampler2D texU; \n"
"uniform lowp sampler2D texV; \n"
"varying mediump vec2 texCoordAtFrag; \n"
"void main() { \n"
" lowp float Y = texture2D(texLum, texCoordAtFrag).r; \n"
" lowp float U = texture2D(texU, texCoordAtFrag).r; \n"
" lowp float V = texture2D(texV, texCoordAtFrag).r; \n"
" lowp float R = 1.164 * (Y - 16.0 / 256.0) + 1.596 * (V - 0.5); \n"
" lowp float G = 1.164 * (Y - 16.0 / 256.0) - 0.813 * (V - 0.5) - 0.391 * (U - 0.5); \n"
" lowp float B = 1.164 * (Y - 16.0 / 256.0) + 2.018 * (U - 0.5); \n"
" gl_FragColor = vec4(R,G,B,1); \n"
"}\r\n";
static char const *vert =
"varying mediump vec2 texCoordAtFrag; \n"
"attribute vec4 Position; \n"
"attribute vec2 TexCoord; \n"
"void main() { \n"
" texCoordAtFrag = TexCoord; \n"
" gl_Position = Position; \n"
"}\r\n";
其中texLum,texU,texV是保存通道的紋理。
Sharpen是卷積濾波器,因此它讀取9個輸入值以產生一個輸出值。 因此,如果您應該在它之前出現另一個着色器並一次操作一個像素,則有一個不錯的論據可以分兩步運行它們(首先進行YUV轉換,然后進行銳化),從而消除重復的計算,甚至如果這不是將着色器組合為封閉框的最簡單方法。
如果要實時組合它們,請將YUV轉換分解為一個單獨的函數,並使用texture2D
過濾器調用該函數,而不是texture2D
。 GL着色器編譯器對您可以鏈接在一起以精確地生成已編譯程序的源文件的數量沒有任何限制,因此您可以遵循通常的編程路線進行函數重用。
如果您希望運行一個,然后運行另一個,則使用中間的“渲染到紋理”階段。 進行YUV變換,然后切換緩沖區,並將其輸出用作銳化的輸入。
實際上,前者實際上可能比后者快,因為YUV變換可能是一種快速的操作(例如,如果是YUV到RGB,則它是一個矩陣乘法),而存儲速度和進行相當大的改變狀態的需求可能是相當昂貴。 如果需要考慮性能,則可能需要進行概要分析。
編輯:因此,從您當前的主語言,您可以將其調整為(在此輸入,如我所願,請原諒錯誤):
"uniform lowp sampler2D texLum; \n"
"uniform lowp sampler2D texU; \n"
"uniform lowp sampler2D texV; \n"
"varying mediump vec2 texCoordAtFrag; \n"
"lowp vec4 yuvTexture2D(mediump vec2 coord) { \n"
" lowp float Y = texture2D(texLum, coord).r; \n"
" lowp float U = texture2D(texU, coord).r; \n"
" lowp float V = texture2D(texV, coord).r; \n"
" lowp float R = 1.164 * (Y - 16.0 / 256.0) + 1.596 * (V - 0.5); \n"
" lowp float G = 1.164 * (Y - 16.0 / 256.0) - 0.813 * (V - 0.5) - 0.391 * (U - 0.5); \n"
" lowp float B = 1.164 * (Y - 16.0 / 256.0) + 2.018 * (U - 0.5); \n"
" return vec4(R,G,B,1.0); \n"
"}\r\n
然后在你的銳化濾鏡你會替代調用texture2D(<whatever>, coord)
與一個呼叫yuvTexture2D(coord)
,具有或者包含在銳化着色器的源代碼列表的片段或將其鏈接到程序。 關於切換到使用矩陣方法,我想您會想要的(為了簡化輸入,我將其格式化為字符串常量以外的其他格式):
uniform lowp sampler2D texLum;
uniform lowp sampler2D texU;
uniform lowp sampler2D texV;
varying mediump vec2 texCoordAtFrag;
const mediump mat4 yuvToRgb =
mat4( 1.164, 1.164, 1.164, -0.07884,
2.018, -0.391, 0.0, 1.153216,
0.0, -0.813, 1.596, 0.53866,
0.0, 0.0, 0.0, 1.0);
lowp vec4 yuvTexture2D(mediump vec2 coord) {
lowp vec4 yuv =
vec4(
texture2D(texLum, coord).r,
texture2D(texU, coord).r,
texture2D(texV, coord).r,
1.0)
return yuvToRgb * yuv;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.