ja szybko się wierzchołek/fragment shader, który z powodzeniem interpoluje kolory:
#ifdef GL_ES
precision highp float;
#endif
uniform vec2 resolution;
void main(void)
{
vec2 p = gl_FragCoord.xy/resolution.xy;
float gray = 1.0 - p.x;
float red = p.y;
gl_FragColor = vec4(red, gray*red, gray*red, 1.0);
}
oto wynik:
Stosowanie go na quad teraz otrzymuje się poprawny wynik, ponieważ interpolacja jest naprawdę wykonywana na całej powierzchni przy użyciu współrzędnych x
i y
. Zobacz szczegółowe wyjaśnienie @ datenwolf, dlaczego tak działa.
Edycja 1 W celu uzyskania pełnej gamy kolorów w funkcjonalnym colorpicker, możliwe jest zmodyfikowanie odcień interaktywnie (patrz https://stackoverflow.com/a/9234854/570738).
demo na żywo w Internecie: http://goo.gl/Ivirl
#ifdef GL_ES
precision highp float;
#endif
uniform float time;
uniform vec2 resolution;
const vec4 kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0);
const vec4 kRGBToI = vec4 (0.596, -0.275, -0.321, 0.0);
const vec4 kRGBToQ = vec4 (0.212, -0.523, 0.311, 0.0);
const vec4 kYIQToR = vec4 (1.0, 0.956, 0.621, 0.0);
const vec4 kYIQToG = vec4 (1.0, -0.272, -0.647, 0.0);
const vec4 kYIQToB = vec4 (1.0, -1.107, 1.704, 0.0);
const float PI = 3.14159265358979323846264;
void adjustHue(inout vec4 color, float hueAdjust) {
// Convert to YIQ
float YPrime = dot (color, kRGBToYPrime);
float I = dot (color, kRGBToI);
float Q = dot (color, kRGBToQ);
// Calculate the hue and chroma
float hue = atan (Q, I);
float chroma = sqrt (I * I + Q * Q);
// Make the user's adjustments
hue += hueAdjust;
// Convert back to YIQ
Q = chroma * sin (hue);
I = chroma * cos (hue);
// Convert back to RGB
vec4 yIQ = vec4 (YPrime, I, Q, 0.0);
color.r = dot (yIQ, kYIQToR);
color.g = dot (yIQ, kYIQToG);
color.b = dot (yIQ, kYIQToB);
}
void main(void)
{
vec2 p = gl_FragCoord.xy/resolution.xy;
float gray = 1.0 - p.x;
float red = p.y;
vec4 color = vec4(red, gray*red, gray*red, 1.0);
adjustHue(color, mod(time, 2.0*PI));
gl_FragColor = color;
}
EDIT 2: W razie potrzeby, shadery do użytku ze współrzędnych tekstur (zastosowanie na quadach z współrzędne tekstury od 0 do 1) powinien wyglądać mniej więcej tak. Bez ograniczeń.
cieniującego fragmenty:
void main(void)
{
vec2 p = gl_TexCoord[0].st;
float gray = 1.0 - p.x;
float red = p.y;
gl_FragColor = vec4(red, gray*red, gray*red, 1.0);
}
Przejściówka werteksach:
void main()
{
gl_TexCoord[0]=gl_MultiTexCoord0;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
Dzięki za odpowiedź, mam bardzo małe doświadczenie z GLSL, chociaż wydaje mi się, że pamiętam, że jeśli chcesz użyć shadera, musisz wszystko zaimplementować, ponieważ całkowicie zastępuje on potok OpenGL? Czy istnieje prosty sposób użycia dostarczonego modułu cieniującego i zastosowanie go tylko do jednego wywołania funkcji glDrawArrays()? –
@ Wola fortuny: Dopóki używasz OpenGL-2.1 i poniżej, możesz używać wybiórczo. To znaczy. do większości rzeczy używaj potokowej funkcji, ale tylko shadery. Tylko z rdzeniem OpenGL-3 i późniejszym * musi * używać shaderów. Ale szczerze: korzystanie z shaderów sprawia, że życie jest o wiele prostsze, więc zdecydowanie polecam je wszędzie. – datenwolf
@ Will-of-fortune Zwykle używam frameworków lub silnika graficznego, co znacznie ułatwia zarządzanie shaderów. Jednak odsyłam do tego: http://nehe.gamedev.net/article/glsl_an_introduction/25007/ Przejdź do "Interfejsu API GLSL Jak używać GLSL w twojej aplikacji OpenGL". W tej sekcji pokażemy, jak włączyć glsl shadery lepiej niż ja w tych komentarzach. – num3ric