2012-10-13 12 views
5

enter image description hereatmosferica dispersione OpenGL 3,3

Al momento sto cercando di convertire uno shader da Sean O'Neil alla versione 330 modo che io possa provare in una scrittura applicazione IM. Sto avendo alcuni problemi con le funzioni deprecate, quindi li ho sostituiti, ma sono quasi completamente nuovo a glsl, quindi probabilmente ho fatto un errore da qualche parte.

shader originale si trova qui: http://www.gamedev.net/topic/592043-solved-trying-to-use-atmospheric-scattering-oneill-2004-but-get-black-sphere/

mio orribile tentativo di convertirli:

Vertex Shader:

#version 330 core 

// Input vertex data, different for all executions of this shader. 
layout(location = 0) in vec3 vertexPosition_modelspace; 
layout(location = 2) in vec3 vertexNormal_modelspace; 



uniform vec3 v3CameraPos;  // The camera's current position 
uniform vec3 v3LightPos;  // The direction vector to the light source 
uniform vec3 v3InvWavelength; // 1/pow(wavelength, 4) for the red, green, and blue channels 
uniform float fCameraHeight; // The camera's current height 
uniform float fCameraHeight2; // fCameraHeight^2 
uniform float fOuterRadius;  // The outer (atmosphere) radius 
uniform float fOuterRadius2; // fOuterRadius^2 
uniform float fInnerRadius;  // The inner (planetary) radius 
uniform float fInnerRadius2; // fInnerRadius^2 
uniform float fKrESun;   // Kr * ESun 
uniform float fKmESun;   // Km * ESun 
uniform float fKr4PI;   // Kr * 4 * PI 
uniform float fKm4PI;   // Km * 4 * PI 
uniform float fScale;   // 1/(fOuterRadius - fInnerRadius) 
uniform float fScaleDepth;  // The scale depth (i.e. the altitude at which the atmosphere's average density is found) 
uniform float fScaleOverScaleDepth; // fScale/fScaleDepth 

const int nSamples = 2; 
const float fSamples = 2.0; 

invariant out vec3 v3Direction; 

// Values that stay constant for the whole mesh. 
uniform mat4 MVP; 
uniform mat4 V; 
uniform mat4 M; 
uniform vec3 LightPosition_worldspace; 



out vec4 dgl_SecondaryColor; 
out vec4 dgl_Color; 


float scale(float fCos) 
{ 
float x = 1.0 - fCos; 
return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); 
} 


void main(void) 
{ 

    //gg_FrontColor = vec3(1.0, 0.0, 0.0); 
     //gg_FrontSecondaryColor = vec3(0.0, 1.0, 0.0); 

// Get the ray from the camera to the vertex, and its length (which is the far point of the ray passing through the atmosphere) 
vec3 v3Pos = vertexPosition_modelspace; 
vec3 v3Ray = v3Pos - v3CameraPos; 
float fFar = length(v3Ray); 
v3Ray /= fFar; 

// Calculate the ray's starting position, then calculate its scattering offset 
vec3 v3Start = v3CameraPos; 
float fHeight = length(v3Start); 
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fCameraHeight)); 
float fStartAngle = dot(v3Ray, v3Start)/fHeight; 
float fStartOffset = fDepth*scale(fStartAngle); 

// Initialize the scattering loop variables 
gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0); 
gl_FrontSecondaryColor = vec4(0.0, 0.0, 0.0, 0.0); 

float fSampleLength = fFar/fSamples; 
float fScaledLength = fSampleLength * fScale; 
vec3 v3SampleRay = v3Ray * fSampleLength; 
vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5; 

// Now loop through the sample rays 
vec3 v3FrontColor = vec3(0.2, 0.1, 0.0); 
for(int i=0; i<nSamples; i++) 
{ 
    float fHeight = length(v3SamplePoint); 
    float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight)); 
    float fLightAngle = dot(v3LightPos, v3SamplePoint)/fHeight; 
    float fCameraAngle = dot(v3Ray, v3SamplePoint)/fHeight; 
    float fScatter = (fStartOffset + fDepth*(scale(fLightAngle) - scale(fCameraAngle))); 
    vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI)); 
    v3FrontColor += v3Attenuate * (fDepth * fScaledLength); 
    v3SamplePoint += v3SampleRay; 
} 

// Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader 
gl_FrontSecondaryColor.rgb = v3FrontColor * fKmESun; 
gl_FrontColor.rgb = v3FrontColor * (v3InvWavelength * fKrESun); 
gl_Position = MVP * vec4(vertexPosition_modelspace,1); 
v3Direction = v3CameraPos - v3Pos; 

dgl_SecondaryColor = gl_FrontSecondaryColor; 
dgl_Color = gl_FrontColor; 


} 

Fragment Shader:

#version 330 core 

out vec4 dgl_FragColor; 

uniform vec3 v3LightPos; 
uniform float g; 
uniform float g2; 

invariant in vec3 v3Direction; 

in vec4 dgl_SecondaryColor; 
in vec4 dgl_Color; 


uniform mat4 MV; 

void main (void) 
{ 

float fCos = dot(v3LightPos, v3Direction)/length(v3Direction); 
float fMiePhase = 1.5 * ((1.0 - g2)/(2.0 + g2)) * (1.0 + fCos*fCos)/pow(1.0 + g2 - 2.0*g*fCos, 1.5); 
dgl_FragColor = dgl_Color + fMiePhase * dgl_SecondaryColor; 
dgl_FragColor.a = dgl_FragColor.b; 



} 

ho scritto una funzione per rendere una sfera, e Sto cercando di rendere questo shader su una versione invertita di esso, la sfera funziona perfettamente, con le normali e tutto il resto. Il mio problema è che la sfera viene resa completamente nera, quindi lo shader non funziona. Modifica: Hai il sole da disegnare, ma il cielo è ancora tutto nero.

Ecco come sto cercando di rendere l'atmosfera all'interno del mio ciclo di rendering principale.

glUseProgram(programAtmosphere); 
    glBindTexture(GL_TEXTURE_2D, 0); 
    //###################### 


glUniform3f(v3CameraPos, getPlayerPos().x, getPlayerPos().y, getPlayerPos().z); 

glm::vec3 lightDirection = lightPos/length(lightPos); 

glUniform3f(v3LightPos, lightDirection.x , lightDirection.y, lightDirection.z); 

glUniform3f(v3InvWavelength, 1.0f/pow(0.650f, 4.0f), 1.0f/pow(0.570f, 4.0f), 1.0f/pow(0.475f, 4.0f)); 

glUniform1fARB(fCameraHeight, 10.0f+length(getPlayerPos())); 

glUniform1fARB(fCameraHeight2, (10.0f+length(getPlayerPos()))*(10.0f+length(getPlayerPos()))); 

glUniform1fARB(fInnerRadius, 10.0f); 

glUniform1fARB(fInnerRadius2, 100.0f); 

glUniform1fARB(fOuterRadius, 10.25f); 

glUniform1fARB(fOuterRadius2, 10.25f*10.25f); 

glUniform1fARB(fKrESun, 0.0025f * 20.0f); 

glUniform1fARB(fKmESun, 0.0015f * 20.0f); 

glUniform1fARB(fKr4PI, 0.0025f * 4.0f * 3.141592653f); 

glUniform1fARB(fKm4PI, 0.0015f * 4.0f * 3.141592653f); 

glUniform1fARB(fScale, 1.0f/0.25f); 


glUniform1fARB(fScaleDepth, 0.25f); 


glUniform1fARB(fScaleOverScaleDepth, 4.0f/0.25f); 


glUniform1fARB(g, -0.990f); 


glUniform1f(g2, -0.990f * -0.990f); 

Qualche idea?

Modifica: aggiornato il codice e aggiunto un'immagine.

+0

è possibile inizializzare le uniformi nel codice sorgente dello shader. E quando hai gl 3.3 allora non hai bisogno di chiamare Arb per Uniforms – Arne

risposta

2

Penso che il problema ci sia, che si scriva su 'FragColor', che può essere una variabile di output 'dead end' nello shader di frammenti, poiché è necessario associarlo esplicitamente a un numero di colore prima di collegare il programma:

glBindFragDataLocation(programAtmosphere,0,"FragColor");

o utilizzare questo in uno shader:

layout(location = 0) out vec4 FragColor

si può tentare di utilizzare il builtin fuori vars invece: gl_FragColor, che è un alias per gl_FragData[0] e quindi uguale al precedente.

EDIT: Ho dimenticato di dire che, quando si utilizzano i comandi incorporati ritirate, è necessario disporre di una dichiarazione di compatibilità:

#version 330 compatibility

EDIT 2: Per testare il legame, mi piacerebbe scrivere un colore costante ad esso per disabilitare eventuali errori di calcolo, poiché questi potrebbero non produrre il risultato previsto, a causa di errori o input zero.

+0

Grazie, ho intenzione di provare questo quando arrivo al computer, ti risponderò appena l'avrò testato! – user1419305

+0

Aggiornamento della domanda! – user1419305

+0

Ok, l'ho risolto! 'GLuint v3InvWavelength = glGetUniformLocation (programAtmosphere, "vInvWavelength");' dovrebbe essere 'GLuint v3InvWavelength = glGetUniformLocation (programAtmosphere, "v3InvWavelength");' – user1419305