GLSL简介 GLSL――OpenGL Shading Language

article/2025/11/9 5:35:49

https://blog.csdn.net/silangquan/article/details/9631341

GLSL简介
         OpenGL着色语言(GLSL――OpenGL Shading Language)是用来在OpenGL中着色编程的语言,也即开发人员写的短小的自定义程序,他们是在图形卡的GPU (Graphic Processor Unit图形处理单元)上执行的,代替了固定的渲染管线的一部分。比如:视图转换、投影转换等。GLSL(GL Shading Language)的着色器代码分成2个部分:Vertex Shader(顶点着色器)和Fragment(片断着色器),有时还会有Geometry Shader(几何着色器)。负责运行顶点着色的是顶点着色器。它可以得到当前OpenGL 中的状态,GLSL内置变量进行传递。它拥有一下的一些特点:

1.是一种高级的过程式语言;

2.作为OpenGL标准的一个部分,也就意味着开源,跨平台;

3.基于C和C++的语法和流程控制;

4.天然支持向量和矩阵的运算;

5.比C和C++更加严格的变量控制;

6.使用变量来处理输入和输出而不是读写文档;

7.Shader的长度并没有限制,也没有必要去查询。

     为什要使用OpenGL shader?

1.增加材料的真材实感 - 石头,草地,木头等等;

2.增加光照效果的真材实感 - 面光源,软阴影等等;

3.高级的渲染效果 - 全局照明,光线追踪等等;

4.非真实的材质 - 模拟画笔效果,钢笔绘制效果等等;

5.阶段贴图 - 动态生成2D和3D的纹理,而不是静态的图像;

6.图像处理 - 卷积,遮罩,复杂混合等;

7.动态效果 - 关键帧插值,粒子系统,动画;

8.可编程反走样方法;

9.通用计算 - 排序,数学建模,流体计算;

这些特性在使用opengl的时候可能可以去实现,但是都会有些局限,而现在,通过shader,我们可以通过显卡的硬件加速来显著增加渲染的速度,同时可以解放CPU。


写一个简单的Shader
首先来看一下电脑的OpenGL环境,终端运行:

glxinfo | grep OpenGL

基于SDL的OpenGL已经安装好(参考这里:SDL入门学习),接下来需要安装一下OpenGL的扩展库。

sudo apt-get install glew-utils libglew1.6

这次先绘制一个简单的矩形。

在工程文件夹下创建一个basic.vert,作为vertex shader.

#version 400
in vec3 VertexPosition;
in vec3 VertexColor;
out vec3 Color;
void main()
{
    Color = VertexColor;
    gl_Position = vec4( VertexPosition, 1.0);
}

·in – for input parameters
·out – for outputs of the function. The returnstatement is also an option for sending the result of a function.
·inout – for parameters that are both input andoutput of a function (新版本的GLSL似乎已经废除)
再创建一个basic.frag,作为fragment shader.

#version 400
void main(void)
{
    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}

创建main.c,代码如下:
/*****************************************************************************
Copyright: 2013, ustc All rights reserved.
contact:k283228391@126.com
File name: main.c
Description:Using opengl shading language in SDL.
Author:Silang Quan
Version: 1.0
Date: 2013.7.30
*****************************************************************************/
#include <SDL/SDL.h>
#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <stdio.h>
#include <stdlib.h>
 
 
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT =800;
const int SCREEN_BPP = 32;
SDL_Surface *screen;
//Whether the window is windowed or not
bool windowed;
//Whether the window is fine
bool windowOK;
//Handler for GLSL program
GLuint programHandle;
GLuint vShader;
GLuint fShader;
 
void quit( int code )
{
    SDL_Quit( );
    /* Exit program. */
    exit( code );
}
 
char *textFileRead(char *fn) {
 
    FILE *fp;
    char *content = NULL;
 
    int count=0;
 
    if (fn != NULL) {
        fp = fopen(fn,"rt");
 
        if (fp != NULL) {
 
      fseek(fp, 0, SEEK_END);
      count = ftell(fp);
      rewind(fp);
 
            if (count > 0) {
                content = (char *)malloc(sizeof(char) * (count+1));
                count = fread(content,sizeof(char),count,fp);
                content[count] = '\0';
            }
            fclose(fp);
        }
    }
    return content;
}
 
void toggle_fullscreen()
{
    //If the screen is windowed
    if( windowed == true )
    {
        //Set the screen to fullscreen
        screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL|SDL_RESIZABLE| SDL_FULLSCREEN );
 
        //If there's an error
        if( screen == NULL )
        {
            windowOK = false;
            return;
        }
 
        //Set the window state flag
        windowed = false;
    }
    //If the screen is fullscreen
    else if( windowed == false )
    {
        //Window the screen
        screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL|SDL_RESIZABLE );
 
        //If there's an error
        if( screen == NULL )
        {
            windowOK = false;
            return;
        }
 
        //Set the window state flag
        windowed = true;
    }
}
 
void handleKeyEvent( SDL_keysym* keysym )
{
    switch( keysym->sym )
    {
    case SDLK_ESCAPE:
        quit( 0 );
        break;
    case SDLK_SPACE:
        break;
    case SDLK_F1:
        toggle_fullscreen();
        break;
    default:
        break;
    }
}
 
void resizeGL(int width,int height)
{
    if ( height == 0 )
    {
        height = 1;
    }
    //Reset View
    glViewport( 0, 0, (GLint)width, (GLint)height );
    //Choose the Matrix mode
    glMatrixMode( GL_PROJECTION );
    //reset projection
    glLoadIdentity();
    //set perspection
    gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );
    //choose Matrix mode
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
}
 
void handleEvents()
{
    // Our SDL event placeholder.
    SDL_Event event;
    //Grab all the events off the queue.
    while( SDL_PollEvent( &event ) ) {
        switch( event.type ) {
        case SDL_KEYDOWN:
            // Handle key Event
            handleKeyEvent( &event.key.keysym );
            break;
        case SDL_QUIT:
            // Handle quit requests (like Ctrl-c).
            quit( 0 );
            break;
        case SDL_VIDEORESIZE:
            //Handle resize event
            screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 16,
                                      SDL_OPENGL|SDL_RESIZABLE);
            if ( screen )
            {
                resizeGL(screen->w, screen->h);
            }
            break;
        }
    }
}
 
void initSDL(int width,int height,int bpp,int flags)
{
    // First, initialize SDL's video subsystem.
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        fprintf( stderr, "Video initialization failed: %s\n",
                 SDL_GetError( ) );
        quit( 1 );
    }
    atexit(SDL_Quit);
    //Set some Attribute of OpenGL in SDL
    SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
 
    //Set the video mode
    screen= SDL_SetVideoMode( width, height, bpp,flags);
    if(!screen )
    {
        fprintf( stderr, "Video mode set failed: %s\n",SDL_GetError( ) );
        quit( 1 );
    windowed=false;
    }
    else windowed=true;
    resizeGL(screen->w, screen->h);
    //Set caption
    SDL_WM_SetCaption( "OpenGL Shading Language Test", NULL );
    
 
}
 
void initShader()
{
    
    vShader = glCreateShader( GL_VERTEX_SHADER );
    fShader = glCreateShader( GL_FRAGMENT_SHADER );
    printf("Here\n");
    if(0 == vShader || 0 == fShader)
    {
        fprintf(stderr, "Error creating vertex shader.\n");
        quit(1);
    }
    
    GLchar* vShaderCode = textFileRead("basic.vert");
    GLchar* fShaderCode = textFileRead("basic.frag");
    const GLchar* vCodeArray[1] = {vShaderCode};
    const GLchar* fCodeArray[1] = {fShaderCode};
    glShaderSource(vShader, 1, vCodeArray, NULL);
    glShaderSource(fShader, 1, fCodeArray, NULL);
    
    glCompileShader(vShader);
    glCompileShader(fShader);
    free(vShaderCode);
    free(fShaderCode);
    //const GLchar* codeArray[] = {shaderCode};
    //Check the compile result
    GLint logLen;
    glGetShaderiv(vShader, GL_INFO_LOG_LENGTH, &logLen);
    if(logLen > 0)
    {
        char *log = (char *)malloc(logLen);
        GLsizei written;
        glGetShaderInfoLog(vShader, logLen, &written, log);
        printf("Shader compile error log: %s\n",log);
        free(log);
    }
    
    programHandle = glCreateProgram();
    if(0 == programHandle)
    {
        fprintf(stderr, "Error creating programHandle.\n");
        quit(1);
    }
    
    glAttachShader(programHandle, vShader);
    glAttachShader(programHandle, fShader);
    glLinkProgram(programHandle);
    //glUseProgram(programHandle);
}
 
void freeShader()
{
    glDetachShader(programHandle, fShader);
    glDetachShader(programHandle, vShader);
    glDeleteShader(fShader);
    glDeleteShader(vShader);
    //glDetachShader(fShader);
    //glDetachShader(vShader);
    //glDetachShader(programHandle);
}
void renderGL()
{
    /* These are to calculate our fps */
    static GLint T0     = 0;
    static GLint Frames = 0;
    // Clear the color and depth buffers.
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    // We don't want to modify the projection matrix. */
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity( );
    // Move down the z-axis.
    glTranslatef( 0.0, 0.0, -5.0 );
    //Draw a square
    glUseProgram(programHandle);
    glBegin(GL_QUADS);
            glVertex2f(-0.5f, -0.5f);
            glVertex2f( 0.5f, -0.5f);
            glVertex2f( 0.5f,  0.5f);
            glVertex2f(-0.5f,  0.5f);
    glEnd();
        // Unbind shader
    glUseProgram(0);
    SDL_GL_SwapBuffers( );
    
    /* Gather our frames per second */
    Frames++;
    {
    GLint t = SDL_GetTicks();
    if (t - T0 >= 5000) {
        GLfloat seconds = (t - T0) / 1000.0;
        GLfloat fps = Frames / seconds;
        printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
        T0 = t;
        Frames = 0;
    }
    }
}
 
void initGL( int width, int height )
{
    float ratio = (float) width / (float) height;
    // Our shading model--Gouraud (smooth).
    glShadeModel( GL_SMOOTH );
    // Set the clear color.
    glClearColor( 0, 0, 0, 0 );
    // Setup our viewport.
    glViewport( 0, 0, width, height );
    //Change to the projection matrix and set our viewing volume.
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 60.0, ratio, 1.0, 100.0 );
}
 
int main( int argc, char* argv[] )
{
 
    // Color depth in bits of our window.
    int flags= SDL_OPENGL|SDL_RESIZABLE;
    //Set the SDL
    initSDL(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,flags);
    if(glewInit() != GLEW_OK) exit(EXIT_FAILURE);
    //Init vertext shader
    initShader();
    //Set the OpenGL
    initGL(SCREEN_WIDTH, SCREEN_HEIGHT );
 
    //main loop
    while(true)
    {
        /* Process incoming events. */
        handleEvents( );
        /* Draw the screen. */
        renderGL( );
    }
    // Free Shader
    freeShader();
    return 0;
}

主要是增加了几个关于Shader的函数,initShader用于shader的初始化,freeShader用于删除shader,释放内存。使用shader之前还需要调用glewInit来初始化glew。

终端编译命令:

g++ main.c -o main -lSDL -lGL -lGLU -lGLEW

解释一下几个相关的API。

GLuint glCreateShader(GLenum shaderType);
Parameter:
 
shaderType – GL_VERTEX_SHADER, GL_GEOMETRY_SHADER, GL_TESS_CONTROL_SHADER, GL_TESS_EVALUATION_SHADER, or GL_FRAGMENT_SHADER.
Return Value:
 
the shader handler

void glShaderSource(GLuint shader, int numOfStrings, const char **strings, int *lengthOfStrings);
Parameters:
 
shader – the handler to the shader.
numOfStrings – the number of strings in the array.
strings – the array of strings.
lengthOfStrings – an array with the length of each string, or NULL, meaning that the strings are NULL terminated.

void glCompileShader(GLuint shader);
Parameters:
 
shader – the handler to the shader.

void glUseProgram(GLuint program);
 Installs a program object as part of current rendering state
Parameters:
program
Specifies the handle of the program object whose executables are to be used as part of current rendering state.


...

整个opengl程序执行的流程如下:

https://blog.csdn.net/silangquan/article/details/9631341

OpenGL 4.0 Shading Language Cookbook
GLSL Core Tutorial – Creating a Shader - http://www.lighthouse3d.com/tutorials/glsl-core-tutorial/creating-a-shader/
Hello GLSL - http://sindney.com/blog/posts/hello-glsl/
OpenGL reference - http://www.opengl.org/sdk/docs/man/


http://chatgpt.dhexx.cn/article/pgLqPaP8.shtml

相关文章

uni-app 拖动滑块验证(插件分享)

插件地址&#xff1a;https://ext.dcloud.net.cn/plugin?id573 效果预览&#xff1a; 作者&#xff1a;黄河爱浪 QQ&#xff1a;1846492969&#xff0c;邮箱&#xff1a;helang.loveqq.com 公众号&#xff1a;web-7258&#xff0c;本文原创&#xff0c;著作权归作者所有&…

Android 自定义View实现拖动滑块完成验证

本文较长&#xff0c;阅读大约十分钟 此效果源自于星球的星友的提问&#xff1a; 周末忙里偷闲把效果实现了一下&#xff0c;其实这个效果一般都是在Web上的验证&#xff0c;手机App多半还是短信验证码等方式&#xff0c;或者WebView加载的JS中的效果&#xff0c;不过要自定义V…

android原生滑块验证

记录一个滑块验证&#xff0c;在文章底部会放上DEMO 简单效果图 1、滑动验证前 2、滑动验证后 用到两个类&#xff1a; 一、自定义类代码 public class ImageAuthenticationView extends android.support.v7.widget.AppCompatImageView {/*** 定义画笔*/private Paint mPai…

小程序 拖动滑块验证(自定义组件 插件分享)

效果图&#xff1a; 文章目录&#xff1a; #1 创建组件 #2 组件编码 MoveVerify.wxss MoveVerify.wxml MoveVerify.js #3 页面引用 在页面的 json 文件中引用组件 在页面的 wxml 文件中使用组件 在页面的 js 文件中接收验证回调 #1 创建组件 在小程序项目根目录创建目…

jQuery拖动滑块验证样式

样式&#xff1a; 目录结构&#xff1a; HTML代码&#xff1a; <!DOCTYPE html> <html><head><title>jQuery仿淘宝网拖动滑块验证码代码</title><meta charset"utf-8"><link href"css/drag.css" rel"stylesh…

css3 滑动验证,Vue 实现拖动滑块验证功能(只有css+js没有后台验证步骤)

vue验证滑块功能&#xff0c;在生活中很多地方都可以见到&#xff0c;那么使用起来非常方便&#xff0c;基于vue如何实现滑块验证呢&#xff1f;下面通过代码给大家讲解。 效果图如下所示&#xff1a; 拖动前 拖动后 代码引用的css与js都是线上的 将代码全部复制到一个html中可…

JavaScript实现拖动滑块验证

Write By Monkeyfly 以下内容均为原创&#xff0c;如需转载请注明出处。 前提 之前在优化别人写的登录界面时&#xff0c;遇到了滑动解锁成功后发送短信验证码的场景&#xff0c;因为涉及到改动&#xff0c;所以必须要明白它是怎么实现的。由于本人JavaScript技艺不精&#…

JavaScript实现拖动滑块验证(方法已封装)

前提 之前写了一篇博文&#xff0c;题目是《JavaScript实现拖动滑块验证》&#xff0c;里面都是用最简单的方式实现的。后来&#xff0c;群里大神推荐了一款unlock.js插件&#xff0c;称作幻灯片解锁插件。在这里附上它的github地址&#xff1a;https://github.com/menthe/unl…

JavaScript封装拖动滑块验证

原生JS封装拖动验证滑块 最终效果分析最终如何使用&#xff1f;编写库的整体初始框架编写核心函数1(创建dom和css)编写核心函数2(绑定事件)添加工具方法(核心函数2中用到的) 最终完整可运行代码使用 最终效果 分析 看到这个效果我们首先应该想到和拖动有关的api: onmousedown, …

vue拖动滑块验证组件

组件Slider.vue <template><div class"drag" ref"dragDiv"><div class"drag_bg"></div><div class"drag_text">{{ confirmWords }}</div><div ref"moveDiv" mousedown"moused…

js实现拖动滑块验证

介绍一个比较6的网站&#xff1a;Element.setPointerCapture() - Web API 接口参考 | MDN 里面用到的setPointerCapture&#xff0c;getBoundingClientRect方法都是这个网站里面有的 &#xff08;看看效果图&#xff0c;动态图我不知道怎么搞&#xff0c;简单来说就是没拉到底…

php拖动滑块验证原理,原生js实现拖动滑块验证

原生js实现拖动滑块验证题 前言 验证的目的是为了减轻超高数据量的访问时,服务器的压力,减少同时请求量;前端基本都不能避免与验证打交道,这里记录一下我对于滑块验证的学习过程。 思路 作为前端,我们要将自己带入用户的角度,对用户的操作习惯进行考虑,我将拖动滑块验证…

Vue - 滑块拖动拼图验证(滑块验证安全检测)

前言 😃 提供您一个示例,您可以轻松移植到您项目中。 您一定见过很多系统都 “配备” 了滑块验证、拼图验证、找不同等, 本质上都是为了验证登录系统的是人还是机器(代码), 如下图所示效果:

Uipath实现简单的滑块拖动验证

本篇文章主要介绍使用【Click】Activities这一个活动来实现拖动滑块的验证&#xff0c;为拖动滑块验证提供了一种思路。但只能应用于滑块从头滑到尾&#xff0c;不支持拼图的滑块验证。 说白了&#xff0c;这篇文章更像是介绍【Click】这个Activities中&#xff0c;"clic…

数据库技术与应用 学习笔记1

1.软件的安装 SQL Server 2019 安装教程 大佬的安装教程链接: https://blog.csdn.net/CHQC388/article/details/104550963. 2.数据库技术与应用 2.1 什么是数据库技术 数据库技术所研究的问题就是如何科学地组织和存储数据&#xff0c;如何高效地获取和处理数据。 2.2 什么…

SQL Server数据库笔记整理(一)

数据库&#xff1a;持久化存储&#xff0c;优化读写&#xff0c;保证数据的有效性。 关系型数据库是基于E-R模型&#xff08;即实体-模型&#xff09;&#xff0c;使用SQL语言进行操作。数据库分类&#xff1a;文档型数据库、服务型数据库&#xff08;使用居多&#xff09; &am…

软件测试工程师学习笔记11 - 数据库篇

软件测试工程师学习笔记 -11 一、入门必读二、Linux三、数据库1.MySQL基础1&#xff09; sql语言的注释2&#xff09;mysql中常用数据类型3&#xff09;表、字段、记录4&#xff09;数据库中的常用命令4&#xff09;字段的约束5&#xff09;总结 一、入门必读 二、Linux 三、…

计算机三级 数据库技术 学习笔记

版权声明&#xff1a;本文为CSDN博主「RanLZ」的原创文章&#xff0c;转载请附上原文出处链接。 计算机三级 数据库技术 第一章 数据库应用系统开发方法 1.1 数据库应用系统生命周期 1.1.1 软件工程与软件开发方法 瀑布模型快速原型模型螺旋模型 1.1.2 DBAS生命周期模型 p …

数据库系统概论复习笔记

Ch1 绪论 1.1 基本概念 数据Data、数据库DB、数据库管理系统DBMS、数据库系统DBS 数据是数据库中存储的基本对象,是用来描述事物的符号。数据库是长期储存在计算机内的、有组织的、可共享的、大量数据的集合。数据库管理系统位于用户与操作系统之间的一层数据管理软件,用于…

数据库系统概论学习笔记(1)

数据库系统第一章 目录 数据库系统第一章1. 绪论1.1 数据库系统概述1.2 数据(Data)图解注意点例子 1.3 数据库(DataBase)注意点1.4 数据库管理系统(DateBase Management System DBMS)1.5 数据库系统(DateBase System,DBS)1.6 数据库管理的三个阶段 1. 绪论 1.1 数据库系统概述…