C++ OpenGL ES Viewer i C# (3 / 8 steg)
Steg 3: Skapa återgivningstillägget
Nästa vi kommer att börja med den kod som behövs för att få något rendering. För detta ändrade jag bara GLES koden som anges i mallen vinkel som drar en snurrande kub. Så nu Lägg en SimpleRenderer klass till nya delade C++-projekt som vi kallar SharedRenderer. Detta kommer delas senare också av andra projekt. Också bara referera till detta projekt i Runtime komponenterna.
Vänligen delade bara börja genom att stänga av förkompilerad headers eftersom detta inte för närvarande spelar bra med Android C++ i VS 2015 RC. Detta beror på att ett VS delat C++ projekt för närvarande inte kan se alla filer i en Android C++ library project. Här hoppas Microsoft fixar det snart. Du kan göra detta genom att gå till sidan vinkel egendom på både vinna och WP och att välja "Inte använder förkompilerat Headers" i fältet "Förkompilerat Header" i gruppen "C/C++".
Jag tänker inte diskutera vad följande GLES kod gör eftersom det är utanför omfånget för handledning. Så bara sätta följande i huvudet:
#pragma en gång
#include < GLES2/gl2.h >
klass SimpleRenderer {
offentlig:
SimpleRenderer();
~ SimpleRenderer();
void Draw();
void UpdateWindowSize (GLsizei bredd, GLsizei höjd);
void Init();
privat:
GLuint mProgram;
GLsizei mWindowWidth;
GLsizei mWindowHeight;
GLint mPositionAttribLocation;
GLint mColorAttribLocation;
GLint mModelUniformLocation;
GLint mViewUniformLocation;
GLint mProjUniformLocation;
GLuint mVertexPositionBuffer;
GLuint mVertexColorBuffer;
GLuint mIndexBuffer;
int mDrawCount;
};
Och följande i filen CPP:
Denna fil används av mallen för att göra en grundläggande scen med GL.
#include "SimpleRenderer.h"
#include "MathHelper.h"
#include < vektor >
#include < sträng >
#include < GLES2/gl2.h >
#include < GLES2/gl2ext.h >
#if defined(WIN_STORE) || defined(WIN_PHONE)
#include < ppltasks.h >
med hjälp av namnområdet plattform;
#endif
#define strängarna #s
GLuint CompileShader(GLenum type, const std::string &source)
{
GLuint shader = glCreateShader(type);
CONST char * sourceArray [1] = {source.c_str()};
glShaderSource (shader, 1, sourceArray, NULL);
glCompileShader(shader);
GLint compileResult;
glGetShaderiv (shader, GL_COMPILE_STATUS, & compileResult);
om (compileResult == 0)
{
GLint infoLogLength;
glGetShaderiv (shader, GL_INFO_LOG_LENGTH, & infoLogLength);
std::Vector infoLog(infoLogLength);
glGetShaderInfoLog (shader, (GLsizei)infoLog.size(), NULL, infoLog.data());
std::wstring errorMessage = std::wstring (L "Shader gick inte:");
errorMessage += std::wstring(infoLog.begin(), infoLog.end());
#if defined(WIN_STORE) || defined(WIN_PHONE)
kasta Exception::CreateException (E_FAIL, ref nya Platform::String(errorMessage.c_str()));
#endif
}
returnera shader;
}
GLuint CompileProgram(const std::string &vsSource, const std::string &fsSource)
{
GLuint program = glCreateProgram();
om (programmet == 0)
{
#if defined(WIN_STORE) || defined(WIN_PHONE)
kasta Exception::CreateException (E_FAIL, L "Program gick inte att skapa");
#else
återvända -1;
#endif
}
GLuint vs = CompileShader (GL_VERTEX_SHADER, vsSource);
GLuint fs = CompileShader (GL_FRAGMENT_SHADER, fsSource);
om (vs == 0 || fs == 0)
{
glDeleteShader(fs);
glDeleteShader(vs);
glDeleteProgram(program);
Return 0;
}
glAttachShader (program, vs);
glDeleteShader(vs);
glAttachShader (program, fs);
glDeleteShader(fs);
glLinkProgram(program);
GLint Link;
glGetProgramiv (program, GL_LINK_STATUS & Link);
om (Link == 0)
{
GLint infoLogLength;
glGetProgramiv (program, GL_INFO_LOG_LENGTH & infoLogLength);
std::Vector infoLog(infoLogLength);
glGetProgramInfoLog (program, (GLsizei)infoLog.size(), NULL, infoLog.data());
std::wstring errorMessage = std::wstring (L "Program länk misslyckades:");
errorMessage += std::wstring(infoLog.begin(), infoLog.end());
#if defined(WIN_STORE) || defined(WIN_PHONE)
kasta Exception::CreateException (E_FAIL, ref nya Platform::String(errorMessage.c_str()));
#else
återvända -1;
#endif
}
returnera programmet;
}
SimpleRenderer::SimpleRenderer():
mWindowWidth(0),
mWindowHeight(0),
mDrawCount(0)
{
}
void SimpleRenderer::Init()
{
Vertex Shader källa
CONST std::string vs = sträng
(
enhetliga mat4 uModelMatrix;
enhetliga mat4 uViewMatrix;
enhetliga mat4 uProjMatrix;
attributet vec4 aPosition;
attributet vec4 aColor;
varierande vec4 vColor;
void main)
{
gl_Position = uProjMatrix * uViewMatrix * uModelMatrix * aPosition;
vColor = aColor;
}
);
Fragmentet Shader källa
CONST std::string fs = sträng
(
precision mediump flyta;
varierande vec4 vColor;
void main)
{
gl_FragColor = vColor;
}
);
Ställ in skuggningen och dess enhetliga/attribut platser.
mProgram = CompileProgram (vs, fs);
mPositionAttribLocation = glGetAttribLocation (mProgram, "aPosition");
mColorAttribLocation = glGetAttribLocation (mProgram, "aColor");
mModelUniformLocation = glGetUniformLocation (mProgram, "uModelMatrix");
mViewUniformLocation = glGetUniformLocation (mProgram, "uViewMatrix");
mProjUniformLocation = glGetUniformLocation (mProgram, "uProjMatrix");
Ställa in kub geometri.
GLfloat vertexPositions [] =
{
-1.0f, - 1.0f, -1.0f,
-1.0f, - 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, - 1.0f, -1.0f,
1.0f, - 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
};
glGenBuffers (1, och mVertexPositionBuffer);
glBindBuffer (GL_ARRAY_BUFFER, mVertexPositionBuffer);
glBufferData (GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
GLfloat vertexColors [] =
{
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f,
};
glGenBuffers (1, och mVertexColorBuffer);
glBindBuffer (GL_ARRAY_BUFFER, mVertexColorBuffer);
glBufferData (GL_ARRAY_BUFFER, sizeof(vertexColors), vertexColors, GL_STATIC_DRAW);
korta index [] =
{
0, 1, 2, / / - x
1, 3, 2,
4, 6, 5, / / + x
5, 6, 7,
0, 5, 1 / / -y
0, 4, 5,
2, 7, 6, / / + y
2, 3, 7,
0, 6, 4, / / - z
0, 2, 6,
1, 7, 3, / / + z
1, 5, 7,
};
glGenBuffers (1, och mIndexBuffer);
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), index, GL_STATIC_DRAW);
}
SimpleRenderer::~SimpleRenderer()
{
om (mProgram! = 0)
{
glDeleteProgram(mProgram);
mProgram = 0;
}
om (mVertexPositionBuffer! = 0)
{
glDeleteBuffers (1, och mVertexPositionBuffer);
mVertexPositionBuffer = 0;
}
om (mVertexColorBuffer! = 0)
{
glDeleteBuffers (1, och mVertexColorBuffer);
mVertexColorBuffer = 0;
}
om (mIndexBuffer! = 0)
{
glDeleteBuffers (1, och mIndexBuffer);
mIndexBuffer = 0;
}
}
void SimpleRenderer::Draw()
{
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
om (mProgram == 0)
hemkomst.
glUseProgram(mProgram);
glBindBuffer (GL_ARRAY_BUFFER, mVertexPositionBuffer);
glEnableVertexAttribArray(mPositionAttribLocation);
glVertexAttribPointer (mPositionAttribLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer (GL_ARRAY_BUFFER, mVertexColorBuffer);
glEnableVertexAttribArray(mColorAttribLocation);
glVertexAttribPointer (mColorAttribLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
MathHelper::Matrix4 modelMatrix = MathHelper::SimpleModelMatrix ((float) mDrawCount / 50.0f);
glUniformMatrix4fv (mModelUniformLocation, 1, GL_FALSE, &(modelMatrix.m[0][0]));
MathHelper::Matrix4 viewMatrix = MathHelper::SimpleViewMatrix();
glUniformMatrix4fv (mViewUniformLocation, 1, GL_FALSE, &(viewMatrix.m[0][0]));
MathHelper::Matrix4 projectionMatrix = MathHelper::SimpleProjectionMatrix(float(mWindowWidth) / float(mWindowHeight));
glUniformMatrix4fv (mProjUniformLocation, 1, GL_FALSE, &(projectionMatrix.m[0][0]));
Rita 36 index: sex ansikten, två trianglar per ansikte, 3 index per triangel
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
glDrawElements (GL_TRIANGLES, (6 * 2) * 3, GL_UNSIGNED_SHORT, 0);
mDrawCount + = 1;
}
void SimpleRenderer::UpdateWindowSize (GLsizei bredd, GLsizei höjd)
{
glViewport (0, 0, bredd, höjd);
mWindowWidth = bredd;
mWindowHeight = höjd;
}
I projektet SharedRenderer måste du också lägga till en MathHelper.h fil med följande innehåll:
#pragma en gång
Detta är några enkla matematiska hjälpare att aktivera mallen för att göra en snurrande kub. Det är inte en komplett math-biblioteket.
Du kan ersätta detta med din favorit math-biblioteket som är lämplig för din målplattformar, e.g. DirectXMath eller GLM.
#include < math.h >
namnområdet MathHelper
{
struct Matrix4
{
Matrix4 (flyta m00 flyta m01, flyta m02, flyta m03,
flyta m10, flyta m11, flyta m12, flyta m13,
flyta m20, flyta m21, flyta m22, flyta m23,
flyta m30, flyta m31, flyta m32, flyta m33)
{
m [0] [0] = m00; m [0] [1] = m01; m [0] [2] = m02; m [0] [3] = m03;
m [1] [0] = m10; m [1] [1] = m11; m [1] [2] = m12; m [1] [3] = m13;
m [2] [0] = m20; m [2] [1] = m21; m [2] [2] = m22; m [2] [3] = m23;
m [3] [0] = m30; m [3] [1] = m31; m [3] [2] = m32; m [3] [3] = m33;
}
float m [4] [4].
};
inline statisk Matrix4 SimpleModelMatrix(float radians)
{
float cosinus = cosf(radians);
float sinus = sinf(radians);
återgå Matrix4 (cosinus, 0.0f,-sinus, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
sinus, 0.0f, cosinus, 0.0f,
0.0f 0.0f, 0.0f, 1.0f);
}
inline statisk Matrix4 SimpleViewMatrix()
{
Kameran är på 60 grader till marken, i YZ-planet.
Kamera Look-At är hårdkodad (0, 0, 0).
Kamera upp är hårdkodad (0, 1, 0).
CONST float sqrt3over2 = 0.86603f;
CONST float cameraDistance = 5.0f;
återgå Matrix4 (1.0f, 0.0f, 0.0f, 0.0f,
0.0f, sqrt3over2, 0.5f, 0.0f,
0.0f, -0.5f, sqrt3over2, 0.0f,
0.0f, 0.0f, - cameraDistance, 1.0f);
}
inline statisk Matrix4 SimpleProjectionMatrix(float aspectRatio)
{
Avlägsna planet är på 50.0f, nära plan är på 1.0f.
FoV är hårdkodad till pi/3.
CONST float cotangens = 1 / tanf (3.14159f/6.0f);
återgå Matrix4 (cotangens/aspectRatio 0.0f, 0.0f, 0.0f,
0.0f, cotangens, 0.0f, 0.0f,
0.0f, 0.0f, -50.0f / (50.0f - 1.0f), (-50.0f * 1.0f) / (50.0f - 1.0f),
0.0f 0.0f, - 1.0f, 0.0f);
}
}
Du bör kunna Kompilera projektet igen just nu. Om inte, gå tillbaka och kolla vad du kanske har missat. Jag rekommenderar också ta bort filerna "Class1.h" och "Class.cpp" i Runtime komponenter som vi inte behöver dem. Att bara skriva ner standardnamnområdet används i dem första som du behöver det senare.