2013-10-04 118 views
0

有人可以幫助我或讓我朝着正確的方向在GLSL代碼中實現DirectX的基本FVF嗎?我完全理解如何創建一個程序,應用VBO等等,但是我在着色器的實際創建中遇到很大困難。即:DirectX類似FVF的GLSL着色器

transformed+lit (x,y,color,specular,tu,tv) 
lit (x,y,z,color,specular,tu,tv) 
unlit (x,y,z,nx,ny,nz,tu,tv) [material/lights] 

有了這個,我會得到足夠的實現更有趣的着色器。

所以,我不是要求一個機制來處理FVF。我只是要求着色器代碼給出適當的流。我明白,未點亮和亮起的版本依賴於傳遞矩陣,我完全理解了這個概念。我只是無法找到顯示這些概念的着色器示例。

+0

這個概念在OpenGL中並不存在。很久以前,有一些非常不靈活的交錯格式,但他們從未接近D3D的FVF的複雜程度,其頂點屬性用於頂點混合,鏡面反射等等。您最好放棄FVF並採用真正的着色器爲中心的頂點緩衝系統。即使在D3D9中,FVF也不贊成使用[頂點聲明](http://msdn.microsoft.com/en-us/library/windows/desktop/bb206335(v = vs.85).aspx)。如果您希望跨API可移植性,這是您應該定位的技術。 –

+0

正如我剛纔所說的,[glInterleavedArrays(...)'](http://www.opengl.org/sdk/docs/man2/xhtml/glInterleavedArrays.xml)是OpenGL最接近FVF的東西,而且在現代OpenGL中甚至不能使用頂點着色器。 –

+0

我正在尋找這些FVF的GLSL中的着色器實現。 –

回答

1

介紹

你沒有指定你的OpenGL針對/ GLSL版本,所以我認爲它至少是OpenGL的3

一個可編程管線的主要優點,與固定功能流水線進行比較,是完全可定製的頂點輸入。我不太確定,如果引入諸如固定頂點格式這樣的約束是一個好主意。爲了什麼?..(你會發現在我的款後的「另一種方式」現代的方法)

但是,如果你真的想模仿固定功能...

  1. 我想您需要爲每個頂點格式 擁有一個頂點着色器,或者以某種方式即時生成頂點着色器。或者甚至是所有着色階段的 。

    例如,對於x, y, color, tu, tv輸入你將有頂點着色器 如:

    attribute vec2 inPosition; 
    attribute vec4 inCol; 
    attribute vec2 inTexcoord; 
    
    void main() 
    { 
    ... 
    } 
    
  2. 當你沒有在OpenGL 3變換,燈光和材料固定的功能,就必須實現它自己:

    • 你必須通過將文件轉換
    • 點亮的着色器矩陣,你必須通過其他變量,如光方向
    • 對於材質着色器,你必須在輸入材料

    通常情況下,在着色器,你有制服或均勻塊做到這一點:

    layout(std140) 
    uniform CameraBuffer 
    { 
        mat4 mtxView; 
        mat4 mtxProj; 
        vec3 cameraPosition; 
    }; 
    
    layout(std140) 
    uniform ObjectBuffer 
    { 
        mat4 mtxWorld; 
    }; 
    
    layout(std140) 
    uniform LightBuffer 
    { 
        vec3 lightDirection; 
    }; 
    
    struct Material 
    { 
        float Ka; 
        float Kd; 
        float Ks; 
        float A; 
    }; 
    
    layout(std140) 
    uniform MaterialBuffer 
    { 
        Material material; 
    }; 
    
  3. 也許,你能以某種方式將所有着色器與不同的格式,制服等在一個大的ubershader與分支。

另一種方式

你能堅持到現代的手法,只是允許用戶聲明頂點格式,他希望(格式,即他在着色器使用)。只需實現類似於IDirect3DDevice9::CreateVertexDeclarationID3D11Device::CreateInputLayout的概念:您將使用glVertexAttribPointer()以及可能的VAO。通過這種方式,您還可以以API獨立方式抽象出頂點佈局。

的主要思路是:

P.S.如果您需要關於如何正確實施光線,GLSL材料(我的意思是在這裏的算法)的想法,你最好拿起一些書或在線教程,而不是在這裏問。或者只是谷歌「GLSL照明」。 你可以發現,有趣以下鏈接:

編碼愉快!

+0

老實說,參考你的#1,我一直在尋找一個完整的版本,你開始展示轉化和點燃的東西。我可能會從那裏建立不亮。我只是想要一個顯示它的例子,所以我可以用正確的方法來做到這一點。我已經對如何使用DirectX彙編着色器手動實現材質有了一個大概的瞭解,所以我只想要一些特定於OpenGL的東西。 –

+0

@ PhoenixX_2用於照明,只需從P.S.中的鏈接中選擇一本書或tutoral即可。如果你需要照明着色器,爲什麼然後你問關於FVF?等等,你說DirectX彙編器? O_O哦,不,你在開玩笑嗎? – Drop

+0

好,讓我再說一遍。你能告訴我一個着色器是什麼樣子,它將採用顏色/鏡面的屏幕座標,並且它的工作方式與DirectX 7相似,所以我可以從我目前正在使用的OpenGL工作實現中移除不帶着色器的着色器,與OpenGL ES 2兼容:)? –

2

好的。如果你在找到工作着色器時遇到麻煩,有例子(老實說,你可以在任何OpenGL書上找到它)。

該着色器程序將使用對象的世界矩陣和相機的矩陣來轉換頂點,然後將一個紋理映射到像素,並使用一個方向光(根據材質屬性和光線方向)點亮它們。

頂點着色器:

#version 330 

// Vertex input layout 
attribute vec3 inPosition; 
attribute vec3 inNormal; 
attribute vec4 inVertexCol; 
attribute vec2 inTexcoord; 
attribute vec3 inTangent; 
attribute vec3 inBitangent; 

// Output 
struct PSIn 
{ 
    vec3 normal; 
    vec4 vertexColor; 
    vec2 texcoord; 
    vec3 tangent; 
    vec3 bitangent; 
}; 

out PSIn psin; 

// Uniform buffers 
layout(std140) 
uniform CameraBuffer 
{ 
    mat4 mtxView; 
    mat4 mtxProj; 
    vec3 cameraPosition; 
}; 

layout(std140) 
uniform ObjectBuffer 
{ 
    mat4 mtxWorld; 
}; 

void main() 
{ 
    // transform position 
    vec4 pos = vec4(inPosition, 1.0f); 
    pos = mtxWorld * pos; 
    pos = mtxView * pos; 
    pos = mtxProj * pos; 
    gl_Position = pos; 

    // just pass-through other stuff 
    psin.normal = inNormal; 
    psin.tangent = inTangent; 
    psin.bitangent = inBitangent; 
    psin.texcoord = inTexcoord; 
    psin.vertexColor = inVertexCol; 
} 

和片段着色器:

#version 330 

// Input 
in vec3 position; 
in vec3 normal; 
in vec4 vertexColor; 
in vec2 texcoord; 
in vec3 tangent; 
in vec3 bitangent; 

// Output 
out vec4 fragColor; 

// Uniforms 
uniform sampler2D sampler0; 

layout(std140) 
uniform CameraBuffer 
{ 
    mat4 mtxView; 
    mat4 mtxProj; 
    vec3 cameraPosition; 
}; 

layout(std140) 
uniform ObjectBuffer 
{ 
    mat4 mtxWorld; 
}; 

layout(std140) 
uniform LightBuffer 
{ 
    vec3 lightDirection; 
}; 

struct Material 
{ 
    float Ka; // ambient quotient 
    float Kd; // diffuse quotient 
    float Ks; // specular quotient 
    float A; // shininess 
}; 

layout(std140) 
uniform MaterialBuffer 
{ 
    Material material; 
}; 

    // function to calculate pixel lighting 
float Lit(Material material, vec3 pos, vec3 nor, vec3 lit, vec3 eye) 
{ 
    vec3 V = normalize(eye - pos); 
    vec3 R = reflect(lit, nor); 

    float Ia = material.Ka; 
    float Id = material.Kd * clamp(dot(nor, -lit), 0.0f, 1.0f); 
    float Is = material.Ks * pow(clamp(dot(R,V), 0.0f, 1.0f), material.A); 
    return Ia + Id + Is; 
} 

void main() 
{ 
    vec3 nnormal = normalize(normal); 
    vec3 ntangent = normalize(tangent); 
    vec3 nbitangent = normalize(bitangent); 

    vec4 outColor = texture(sampler0, texcoord); // texture mapping 

    outColor *= Lit(material, position, nnormal, lightDirection, cameraPosition); // lighting 

    outColor.w = 1.0f; 

    fragColor = outColor; 
} 

如果你不想紋理,只是不樣本紋理,但等同outColorvertexColor

如果您不需要照明,只需註釋掉Lit()函數。

編輯: 對於二維對象,你仍然可以使用相同的程序,但許多功能將是多餘的。你可以去掉:

  • 相機
  • 材料
  • 所有頂點attribute S的,但inPositioninTexcoord(也許還inVertexCol,F您需要的頂點有顏色)和所有的代碼與不必要的attribute S的相關
  • inPosition可以vec2
  • ,你將需要通過正交p而不是透視矩陣
  • 您甚至可以去除矩陣,並將像素位置的頂點緩衝區傳遞給頂點緩衝區。請參閱我的回答here,瞭解如何將這些像​​素位置轉換爲屏幕空間位置。您可以在C/C++代碼或GLSL/HLSL中執行此操作。

希望它有助於某種程度。

+0

'tint'的用途是什麼?那麼UI元素的位置是2D還是相對於屏幕呢?只需傳入適當的設置矩陣? –

+0

'tint'只是一種顏色,可以用來調試特定對象(例如,用於調試目的或鼠標懸停)。我編輯了答案並將其刪除,因爲它未在着色器程序中使用。另外我添加了關於2D的信息。 – Drop

+0

這就是我所設想的所有OpenGL ES兼容嗎? –