Estoy tratando de hacer que este sombreador se ejecute en un iDevice muy antiguo, así como eventualmente en Android.
Incluso cuando reduzco el código a 2 funciones sinusoidales por fragmento, el sombreador se ejecuta a aproximadamente 20 fps.
He considerado sacar una hoja del libro de viejas técnicas de sombreado y crear una matriz que contenga un montón de valores trigonométricos predefinidos y de alguna manera usarlos para aproximar el sombreador.
En el sombreador que vinculé anteriormente, ya estoy simulando que al redondear los valores enviados a la función trigonométrica, cuanto más a la izquierda del mouse (mientras está hacia abajo), disminuye la calidad del sombreador. En realidad, es bastante genial porque muy cerca del lado izquierdo parece un sombreador completamente diferente y bastante genial.
De todos modos tengo dos dilemas:
- No sé cuál es la forma más eficiente de tener una matriz de valores similares a 360 en un sombreador GLSL, constante o uniforme.
No puedo encontrar la manera de poner un número en un rango, por lo general, si quisiera un ángulo entre 0 y 360 (sí, sé que las GPU usan radianes). Lo haría así.
func range(float angle) { float temp = angle while (temp > 360) {temp -= 360;} while (temp < 0) {temp += 360;} return temp; }
Sin embargo, GLSL no permite bucles while o funciones recursivas.
fuente
mod
función incorporada es lo que desea. Tu escribiriasmod(angle, 360.0)
.Respuestas:
Se ha sugerido en comentarios repetidamente, pero nadie sintió la necesidad de dar una respuesta adecuada, por lo que, en aras de la exhaustividad, una solución directa y común a este problema podría ser usar una textura como tabla de búsqueda, específicamente una textura 1D que contiene todos los valores de su función para el posible rango de entrada (es decir, / ). Esto tiene varias ventajas:[0,360) [0,2π)
GL_REPEAT
como modo de ajuste para la textura y comenzará automáticamente al principio nuevamente cuando acceda con argumentos> 1 (y de manera similar para argumentos negativos).GL_LINEAR
como filtro de textura, de esta manera obtienes valores que ni siquiera almacenaste. Por supuesto, la interpolación lineal no es 100% precisa para las funciones trigonométricas, pero ciertamente es mejor que ninguna interpolación.float sin = 2.0 * (texValue.r + texValue.g / 256.0) - 1.0;
Por supuesto, todavía tiene que evaluarse si esta es una mejor solución, ya que el acceso a la textura tampoco es totalmente gratuito, así como cuál sería la mejor combinación de tamaño y formato de textura.
En cuanto a rellenar la textura con datos y abordar uno de sus comentarios, debe tener en cuenta que el filtrado de textura devuelve el valor exacto en el centro de texel , es decir, una coordenada de textura a la mitad del tamaño del texel. Entonces sí, debe generar valores en
.5
texels , es decir, algo así en el código de la aplicación:Sin embargo, es posible que aún desee comparar el rendimiento de este enfoque con un enfoque que usa una matriz uniforme pequeña (es decir[0,360)
uniform float sinTable[361]
, o tal vez menos en la práctica, vigile el límite de su implementación en el tamaño de matriz uniforme) que simplemente carga con los valores respectivos usandoglUniform1fv
y acceda ajustando su ángulo a usando la función y redondeándolo al valor más cercano:mod
fuente