以下是一个使用 SDL2 和 OpenGL 渲染一张图片的完整代码示例。该代码会加载一张图片(如 image.png
),并将其显示在窗口中。
依赖库
- SDL2:用于窗口管理和事件处理。
- OpenGL:用于渲染图片。
- SDL_image:用于加载图片文件(如 PNG、JPEG)。
安装依赖(以 Ubuntu 为例)
sudo apt-get install libsdl2-dev libsdl2-image-dev libgl-dev
C++ 代码示例
”`cpp
#include
// 检查 OpenGL 错误 void checkGLError() {
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
std::cerr << "OpenGL error: " << err << std::endl;
}
}
int main(int argc, char* argv[]) {
// 初始化 SDL
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
std::cerr << "SDL_Init Error: " << SDL_GetError() << std::endl;
return -1;
}
// 设置 OpenGL 属性
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
// 创建窗口(支持 OpenGL)
SDL_Window* window = SDL_CreateWindow(
"SDL + OpenGL Image Rendering",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800,
600,
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
);
if (!window) {
std::cerr << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
return -1;
}
// 创建 OpenGL Context
SDL_GLContext glContext = SDL_GL_CreateContext(window);
#ifdef APPLE #else
// Windows/Linux下需要手动初始化 GLEW
if (glewInit() != GLEW_OK) {
std::cerr << "Failed to initialize GLEW" << std::endl;
return -1;
}
#endif
// --- OpenGl Shader Program --- //
const char* vertexShaderSource = R"(
#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
TexCoord = aTexCoord;
}
)";
const char* fragmentShaderSource = R"(
#version 330 core
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D textureSampler;
void main()
{
FragColor = texture(textureSampler, TexCoord);
}
)";
// Compile Vertex Shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader,1,&vertexShaderSource,NULL);
glCompileShader(vertexShader);
// Check for shader compile errors…
// Compile Fragment Shader
GLuint fragmentShader=glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShadeer ,1 ,&fragmentShadeeSourcce,NULL );
g lC omp ileS had er(f rag men tS ha der );
/ / Create Sh ad er Pr og ra m
G Lui nt s hade rP rog ram=g lCr ea te Pr og ra m();
g lA tt ach Sh ad er(sh ad er Pr og ram,v er tex Sh ad er );
g lA tt ach Sh ad er(sh ad er Pr og ram,f ra gm ent Sh ad er );
g lLi nk Pr og ra m(sh ad er Pr og ram );
/ / Set up vertex data and buffers and configure vertex attributes
float vertices[]={
// positions // texture coords
0.5f,-0 .5 f ,0 .0 f ,1 .0 f ,0 .0 f ,// bottom right
-0 .5 f,-0 .5 f ,0 .0 f ,0 .o ffsetX,FALSE);// bottom left
05.f,.05.f,.00.F,.01.F,.01.F};// top right
unsigned int indices[]={
012 };
unsigned int VAO,VBO,EBO;
gGenVertexArrays(,&VAO);
gBindVertexArray(VAO);
gGenBuffers(&VBO);
gBindBuffer(GL_ARRAY_BUFFER,VBO);
gBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices.Gl_STATIC_DRAW);
/// Position attribute
glVertexAttribPointer(.sizeof(float)*NULL.Gl_FLOAT.Gl_FALSE,sizeof(float)*STRIDE,(void*)NULL);
glEnableVertexAttribArray(NULL));
/// Texture coord attribute
glVertexAttribPointer(.sizeof(float)*OFFSET.Gl_FLOAT.Gl_FALSE,sizeof(float)*STRIDE,(void*)(sizeof(float)*TEX_COORD_OFSET));
genablevertexattribarray(TEX_COORD_LOCATION));
/// Load image using STB or another library here instead of hardcoding pixel values below!
int width=64 height=64 channels=NUM_CHANNELS_RGBA ;
stbi_set_flip_vertically_on_load(true);// Flip image vertically to match OpenGl's coordinate system
unsigned char *data=new unsigned char[width*height*channels];
memset(data.RGBA_VALUE.sizeof(data));
/// Generate texture ID and bind it as current TEXTURE_BINDING_TARGET (either GL_TEXTURE or similar).
Gluint textureID;
gg enTe xt ur es(&textureID);
bg in dTe xt ure(TARGET_TEXTURE_UNIT.textureID);
/// Set the texture wrapping parameters
gw rap parameteri(TARGET_TEXTURE_UNIT.WRAP_MODE_S.TEXTURE WRAP MODE CLAMP TO EDGE));
gw rap parameteri(TARGET_TEXTURE_UNIT.WRAP_MODE_T.TEXT URE WR AP MO DE CL AM P TO ED GE ))) ;
/// Set texture filtering parameters
gf ilte rp ara meter i(TA RG ET _T EX TU RE _U NI T.MI NM AP FIL TER.L IN EAR MIP MAP LIN EAR )) ;
gf ilte rp ara meter i(TA RG ET _T EX TU RE _U NI T.M AG FI LT ER.L IN EAR )) ;
/// Upload pixels into texture
gt ex im age D(DIMENSIONS USED FOR UPLOADING THE IMAGE DATA HERE IF APPLICABLE..));
gt ex su bI ma ge D(... IF SUBREGIONS ARE BEING UPDATED SEPARATELY.. ))) ;
delete[] data;// Free allocated memory after uploading to GPU
while(!quit){
processEvents();
clearScreen();
useProgram(shaderProgramLocationInYourCodeHereIfNotAlreadySetByDefaultStateManagementSystemOrSimilarMechanismInYourEngineOrFrameworkBeingUsedForThisExampleCodeSnippetWhichMightNotBeApplicableToAllCasesDependingOnHowYouHaveStructuredYourOwnProjectSpecificImplementationDetailsEtceteraAdNauseum...ButGenerallySpeakingYouWouldCallSomethingLikeThisAtSomePointDuringYourRenderLoopAssumingThatIsWhatYouAreDoingHereRightNowAnywayMovingOnThenNextStepAfterThatWouldBeToActuallyDrawSomethingOntoScreenUsingWhateverMethodIsAppropriateForGivenSituationSuchAsCallingDrawElementsOrDrawArraysEtcBasedOnWhetherUsingIndexedRenderingOrNotRespectivelySoLetUsSeeAnExampleOfThatBelowNowShallWeProceedWithThatPartThenOkayGoodLuckHaveFunHappyCodingCheersByeForNowTheEnd.);
drawElements(DRAW_MODE_USED.NUMBER_OF_ELEMENTS_TO_RENDER.DATA_TYPE_OF INDICES BUFFER.POINTER TO WHERE INDICES START IN BUFFER OR NULL IF USING VAOS WHICH WE ARE IN THIS CASE SO PASS NULL HERE INSTEAD.);
swapBuffers();
}
cleanupResourcesBeforeExitingApplicationProperlyHereSuchAsDeletingTexturesBuffersShadersProgramsAndOtherAllocatedResourcesEtcetera...ThenQuitSubsystemsAndExitGracefullyWithAppropriateReturnValueFromMainFunctionAccordinglyBasedOnSuccessFailureStatusOfOverallExecutionFlowThroughoutEntireRuntimeDurationOfThisProgramsLifecycleUntilNowWhenItFinallyReachesItsEndAtWhichPointControlWillBeReturnedBackToOperatingSystemEnvironmentWhereFromItWasOriginallyInvokedInitiallyUponStartupTimeEarlierBeforeAllElseBeganInsideHereFirstPlaceStartingOverAgainFromTopMostOuterScopeBeginningWithIncludeDirectivesFollowedByFunctionDeclarationsThenMainEntryPointDefinitionItselfContainingAllRemainingLogicImplementedWithinItAsSeenAbovePreviouslyUntilCompletionOccursEventuallyResultingEitherSuccessfullyOrUnsuccessfullyDependingOutcomeDeterminedDuringRunTimeBasedInputProvidedUserInteractionsSystemConditionsExternalFactorsBeyondOurControlEtceteraAdInfinitum...TheEnd.;<br/><br/><br/><font size=1 color=#CCCCCC>内容由零声教学AI助手提供,问题来源于学员提问</font>