2011-06-02 9 views

Respuesta

10

Voy a asumir que tiene un simple vertex shader controversial, ya que no es realmente relevante para la cuestión, tales como:

void main() 
{ 
    gl_Position = modelviewProjectionMatrix * position; 
    texCoordVarying = vec2(textureMatrix * vec4(texCoord0, 0.0, 1.0)); 
} 

Así que hace mucho lo mismo que ES 1.x sería si la iluminación estuviera desactivada, incluida la matriz de textura que casi nadie usa.

No soy un experto en Photoshop, así que por favor perdone mis declaraciones de lo que creo que hacen las diversas herramientas, especialmente si estoy equivocado.

Creo que estoy en lo correcto al decir que la herramienta de niveles efectivamente estira (y recorta) el histograma de brillo? En ese caso, un ejemplo podría ser shader:

varying mediump vec2 texCoordVarying; 
uniform sampler2D tex2D; 

const mediump mat4 rgbToYuv = mat4(0.257, 0.439, -0.148, 0.06, 
            0.504, -0.368, -0.291, 0.5, 
            0.098, -0.071, 0.439, 0.5, 
            0.0,  0.0,  0.0, 1.0); 

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); 

uniform mediump float centre, range;  

void main() 
{ 
    lowp vec4 srcPixel = texture2D(tex2D, texCoordVarying); 
    lowp vec4 yuvPixel = rgbToYuv * srcPixel; 

    yuvPixel.r = ((yuvPixel.r - centre) * range) + 0.5; 

    gl_FragColor = yuvToRgb * yuvPixel; 
} 

te había que controlar ajustando el centro del rango que desea para dejar pasar (que se trasladará al centro del rango de salida) y el rango total desea dejar pasar (1.0 para todo el rango, 0.5 para la mitad del rango, etc.).

Una cosa de interés es que paso del espacio de entrada RGB a un espacio de color YUV para el ajuste intermedio. Lo hago usando una multiplicación de matrices. Luego ajuste el canal de brillo y aplique otra matriz que se transforma de YUV a RGB. Para mí, tenía mucho sentido trabajar en un espacio de color luma/croma y, a partir de ahí, elegí YUV de manera bastante arbitraria, aunque tiene la gran ventaja de ser una transformada lineal simple de espacio RGB.

Entiendo que la herramienta Curvas también reasigna el brillo, pero de acuerdo con alguna función f (x) = y, que es monótonamente creciente (por lo que se cruza horizontal o verticalmente solo una vez) y se establece en la interfaz como una curva desde la parte inferior izquierda a la parte superior derecha de alguna manera.

Como GL ES no es fantástico con estructuras de datos y se deben evitar las ramificaciones donde sea posible, sugiero la mejor forma de implementar que es cargar una textura de luminancia de 256x1 donde el valor en 'x' es f (X). Luego puede hacer un mapa a través de la textura secundaria, p. con:

... same as before down to ... 
lowp vec4 yuvPixel = rgbToYuv * srcPixel; 

yuvPixel.r = texture2D(lookupTexture, vec2(yuvPixel.r, 0.0)); 

... and as above to convert back to RGB, etc ... 

Está utilizando una unidad de textura de repuesto para indexar una tabla de búsqueda, efectivamente. En los dispositivos iOS que admiten ES 2.0, se obtienen al menos ocho unidades de textura, por lo que es de esperar que tenga una de repuesto.

Los ajustes de tono/saturación son más difíciles de mostrar porque la asignación de RGB a HSV implica muchos condicionales, pero el proceso es básicamente el mismo: realice un mapa de RGB a HSV, realice las modificaciones que desee en H y S, mapa de regreso a RGB y salida.

Sobre la base de una rápida búsqueda en Google, this site ofrece algo de código descargable que incluye algunas funciones de Photoshop (aunque no las curvas o niveles tales que puedo ver) y, significativamente, los suministros ejemplos de implementaciones de funciones RGBToHSL y HSLToRGB. Es para GLSL de escritorio, que tiene variables, tipos y funciones más predefinidos, pero no debería tener ningún problema grande para solucionarlo. Solo recuerde agregar modificadores de precisión y suministrar sus propios reemplazos para las funciones ausentes min y max.

6

Para curvas, photoshop utiliza interpolación spline bicúbica.Para un conjunto dado de puntos de control, puede precalcular los 256 valores para cada canal y para la curva maestra. Descubrí que es más fácil almacenar los resultados como una textura de 256x1 y pasarlos al sombreador y luego cambiar los valores de cada componente:

uniform sampler2D curvesTexture; 

vec3 RGBCurvesAdjustment(vec3 color) 
{ 
    return vec3(texture2D(curvesTexture, vec2(color.r, 1.0)).r, 
       texture2D(curvesTexture, vec2(color.g, 1.0)).g, 
       texture2D(curvesTexture, vec2(color.b, 1.0)).b); 
} 
Cuestiones relacionadas