Skip to content
Snippets Groups Projects
Commit b25eb9b6 authored by Noé's avatar Noé
Browse files

Adding the projet

parent bfb49b7a
No related branches found
No related tags found
No related merge requests found
Showing
with 941 additions and 0 deletions
name: Linux
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build-Ubuntu:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup
run:
sudo apt-get update;
sudo apt-get install libglfw3-dev;
- name: Configure CMake
working-directory: examples/00_empty_3D_scene
run: cmake -B build/ -DCMAKE_BUILD_TYPE=RelWithDebInfo
- name: Build
working-directory: examples/00_empty_3D_scene/build
run: make -j$(nproc)
- name: Compile Unit test
working-directory: examples/test_cgp/
run: make -j$(nproc)
- name: Run Unit test
working-directory: examples/test_cgp/
run: ./test_cgp
\ No newline at end of file
name: MacOS
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build-MacOS:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: Configure CMake
working-directory: examples/00_empty_3D_scene
run: cmake -B build/ -DCMAKE_BUILD_TYPE=RelWithDebInfo
- name: Build
working-directory: examples/00_empty_3D_scene/build
run: make -j$(nproc)
\ No newline at end of file
name: Windows
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build-Windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: Configure CMake
working-directory: examples/00_empty_3D_scene
run: cmake -B build/ -DCMAKE_BUILD_TYPE=RelWithDebInfo
- name: Build
working-directory: examples/00_empty_3D_scene
run: cmake --build build/ --config RelWithDebInfo
MIT License
Copyright (c) 2022 Damien Rohmer <damien.rohmer@polytechnique.edu>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file
# CGP - Computer Graphics Programming Library
![BuildWindows](https://github.com/drohmer/CGP/actions/workflows/Windows.yml/badge.svg)
![BuildLinux](https://github.com/drohmer/CGP/actions/workflows/Linux.yml/badge.svg)
![BuildMacOS](https://github.com/drohmer/CGP/actions/workflows/MacOS.yml/badge.svg)
- [Introduction](#Introduction)
- [Compile the library](#Compilation)
<a name="Introduction"></a>
## Introduction
[CGP - Computer Graphics Programming -](https://imagecomputing.net/cgp/index.html) is a lightweight and minimalist C++ library using OpenGL to represent, animate, and interact with 3D scenes.
It features a set of simple structures and functions (vectors, matrices, mesh structures, transforms, camera, etc) that are simple to use and read. The objective is to save time compared to raw OpenGL coding, while preserving the fundamental logic and comprehension of high-performance Graphics. The 3D scene can be exported as a Webpage via Emscripten scripts.
The main objective of CGP is to provide
* **Easy to use CG basic tools**.
* **Data and structure ready for simple interaction and animation**.
* **Helping structures and functions that do not impose a framework**.
* **Easy to read and understand source code**.
* **Secured and easy to debug code**.
### Additional documentation
[CGP Webpage](https://imagecomputing.net/cgp/index.html)
Examples of CGP-based codes can be found in [examples/](examples/)
<a name="Compilation"></a>
## Compile the library
The directory _library/_ contains the source code of CGP, while the directory _examples/_ contains a set of example scenes.
Each example is an independent program with its own CMakeLists.txt and/or Makefile.
CGP requires
* A C++14 (or greater) compatible compiler (GCC/CLang, or a recent Visual Studio).
* An OpenGL 3.3 (or greater) compatible system.
* [libGLFW](https://www.glfw.org/) and [pkgconfig](https://www.freedesktop.org/wiki/Software/pkg-config/) installed on Linux system.
### Linux
System setup
```c++
sudo apt install build-essential pkg-config cmake
sudo apt install libglfw3-dev
```
Building examples/00_empty_3D_scene/ (via CMake)
```c++
cd examples/00_empty_3D_scene/
cmake -B build/
cd build/
make -j$(nproc)
./00_empty_3D_scene
```
_Alternative_: Building examples/00_empty_3D_scene/ (via Makefile)
```c++
cd examples/00_empty_3D_scene/
make -j$(nproc)
./00_empty_3D_scene
```
### Windows
**Method 1**. Create a Visual Studio project using CMake
* You may use the following batch script: examples/00_empty_3D_scene/scripts/__windows_cmake_visual.bat__
_Once opened by Visual Studio, the project should be configured to compile and be executed directly without further setup. Make sure your Windows version is updated for Visual Studio to be able to compile correctly C++14._
**Method 2**. Install MinGW from [MSYS2](https://www.msys2.org/).
* You may use the following batch script: examples/00_empty_3D_scene/scripts/__windows_compile_mingw.bat__
* You may build/edit the project using VS Code.
### MacOS
Building examples/00_empty_3D_scene/ (via CMake)
```c++
cd examples/00_empty_3D_scene/
cmake -B build/
cd build/
make -j$(nproc)
./00_empty_3D_scene
```
### Detailed system set-up and compilation
A detailed tutorial on how to install and compile C++ code is available here if needed: [Detailed installation and compilation for CGP](https://imagecomputing.net/cgp/compilation).
## Export result as a Website
CGP is set to be compatible with [Emscripten](https://emscripten.org/) compilation. A website template and compilation script is provided for Linux system (emscripten must be installed).
Generating a website for examples/00_empty_3D_scene/
```c++
$ cd examples/00_empty_3D_scene/
$ python scripts/linux_compile_emscripten.py
$ emrun index.html
```
\ No newline at end of file
# This is a generic CMake setup for CGP library use
cmake_minimum_required(VERSION 3.8)
# Relative path to the CGP library
# => You may need to adapt this directory to your relative path in the case you move your directory
set(PATH_TO_CGP "../../library/" CACHE PATH "Relative path to CGP library location")
# Check that the path to the library is correct
get_filename_component(ABS_PATH_TO_CGP ${PATH_TO_CGP} ABSOLUTE)
if(NOT EXISTS ${ABS_PATH_TO_CGP})
message(ERROR " Could not import the CGP library using the relative path ${directory_to_library} - please adjust this path in the CMakeLists.txt")
else()
message(STATUS "The relative path to the library is set to ${PATH_TO_CGP}")
message(STATUS "The absolute path to the library is set to ${ABS_PATH_TO_CGP}")
endif()
# Compile for Release with Debug Info
set(CMAKE_BUILD_TYPE RelWithDebInfo)
# List the files of the current local project
# Default behavior: Automatically add all hpp and cpp files from src/ directory, and .glsl from shaders/
# You may want to change this definition in case of specific file structure
file(GLOB_RECURSE src_files ${CMAKE_CURRENT_LIST_DIR}/src/*.[ch]pp ${CMAKE_CURRENT_LIST_DIR}/shaders/*.glsl)
# Generate the executable_name from the current directory name
get_filename_component(executable_name ${CMAKE_CURRENT_LIST_DIR} NAME)
# Another possibility is to set your own name: set(executable_name your_own_name)
message(STATUS "Configure steps to build executable file [${executable_name}]")
project(${executable_name})
# Add current src/ directory
include_directories("src")
# Add the lib directory
include_directories(${ABS_PATH_TO_CGP})
# Include files from the CGP library (as well as external dependencies)
message(STATUS "Include CGP lib and external dependencies files from relative path")
include(${ABS_PATH_TO_CGP}/CMakeLists.txt)
add_definitions(-DSOLUTION)
# Uncomment the following line to remove assertion checks from CGP library (for full efficiency)
# add_definitions(-DCGP_NO_DEBUG)
# Add all files to create executable
# @src_files: the local file for this project
# @src_files_cgp: all files of the cgp library
# @src_files_third_party: all third party libraries compiled with the project
add_executable(${executable_name} ${src_files_cgp} ${src_files_third_party} ${src_files})
# Set Compiler for Unix system
if(UNIX)
set(CMAKE_CXX_COMPILER g++) # Can switch to clang++ if prefered
add_definitions(-g -O2 -std=c++14 -Wall -Wextra -Wfatal-errors -Wno-pragmas) # Can adapt compiler flags if needed
add_definitions(-Wno-sign-compare -Wno-type-limits) # Remove some warnings
endif()
# Set Compiler for Windows/Visual Studio
if(MSVC)
set(CMAKE_CONFIGURATION_TYPES RelWithDebInfo ) # default build as RelWithDebInfo
set_property( DIRECTORY PROPERTY VS_STARTUP_PROJECT ${executable_name} ) # default project (avoids AllBuild)
set_target_properties( ${executable_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}$<0:> ) # default output in root dir
set_target_properties( ${executable_name} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) # default debug execution in root dir
# Avoids the warning /W3 overided by /W4 when using Ninja
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
add_definitions(/MP /wd4244 /wd4127 /wd4267 /wd4706 /wd4458 /wd4996 /wd26495 /openmp) # Parallel build (/MP) + disable some warnings
source_group(TREE ${CMAKE_SOURCE_DIR} FILES ${src_files}) #Allow to explore source directories as a tree in Visual Studio
endif()
# Link options for Unix
target_link_libraries(${executable_name} ${GLFW_LIBRARIES})
if(UNIX)
target_link_libraries(${executable_name} dl) #dlopen is required by Glad on Unix
endif()
# This Makefile will generate an executable file named 00_empty_3D_scene
# This path should point to the CGP library depending on the current directory
## You may need to it in case you move the position of your directory
PATH_TO_CGP = ../../library/
TARGET ?= 00_empty_3D_scene #name of the executable
SRC_DIRS ?= src/ $(PATH_TO_CGP)
CXX = g++ #Or clang++
SRCS := $(shell find $(SRC_DIRS) -name *.cpp -or -name *.c -or -name *.s)
OBJS := $(addsuffix .o,$(basename $(SRCS)))
DEPS := $(OBJS:.o=.d)
INC_DIRS := . $(PATH_TO_CGP)
INC_FLAGS := $(addprefix -I,$(INC_DIRS)) $(shell pkg-config --cflags glfw3)
CPPFLAGS += $(INC_FLAGS) -MMD -MP -DIMGUI_IMPL_OPENGL_LOADER_GLAD -g -O2 -std=c++14 -Wall -Wextra -Wfatal-errors -Wno-sign-compare -Wno-type-limits -Wno-pragmas -DSOLUTION # Adapt these flags to your needs
LDLIBS += $(shell pkg-config --libs glfw3) -ldl -lm # Adapt this lib depending on your system (lib glfw is usually at -lglfw)
$(TARGET): $(OBJS)
echo $(CURDIR)
$(CXX) $(LDFLAGS) $(OBJS) -o $@ $(LOADLIBES) $(LDLIBS)
.PHONY: clean
clean:
$(RM) $(TARGET) $(OBJS) $(DEPS)
-include $(DEPS)
\ No newline at end of file
# This Makefile can be called by emscripten to generate a webpage
# Usage:
# $ emmake -f Makefile_emscripten
# $ emrun index.html
# This path should point to the CGP library depending on the current directory
## You may need to it in case you move the position of your directory
PATH_TO_CGP = ../../library/
TARGET ?= index.html
SRC_DIRS ?= src/ $(PATH_TO_CGP)
CXX = emcc
SRCS := $(shell find $(SRC_DIRS) -name *.cpp -or -name *.c -or -name *.s)
OBJS := $(addsuffix .o,$(basename $(SRCS)))
DEPS := $(OBJS:.o=.d)
INC_DIRS := . $(PATH_TO_CGP)
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
CPPFLAGS += $(INC_FLAGS) -MMD -MP -DIMGUI_IMPL_OPENGL_LOADER_GLAD -O2 -std=c++14 -Wall -Wextra -Wfatal-errors -Wno-sign-compare -Wno-type-limits -Wno-pragmas -DSOLUTION -DCGP_NO_DEBUG
LDLIBS += -ldl -lm -sMAX_WEBGL_VERSION=2 -s USE_GLFW=3 -s ALLOW_MEMORY_GROWTH=1 --preload-file shaders/ --preload-file assets/
$(TARGET): $(OBJS)
echo $(CURDIR)
$(CXX) $(LDFLAGS) $(OBJS) -o $@ $(LOADLIBES) $(LDLIBS)
cp scripts/emscripten_template.html index.html
.PHONY: clean
clean:
$(RM) $(TARGET) $(OBJS) $(DEPS)
-include $(DEPS)
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
* {
margin: 0;
padding: 0;
}
#canvas {
background-color: black;
}
</style>
</head>
<body>
<canvas id="canvas" width="600" height="600" oncontextmenu="event.preventDefault()"></canvas>
<script type='text/javascript'>
var Module = {
canvas: (function() {
var canvas = document.getElementById('canvas');
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
return canvas;
})(),
};
</script>
<script async type="text/javascript" src="index.js"></script>
<script async type="text/javascript">
resize();
window.addEventListener("resize", resize);
function resize()
{
canvas.width = window.innerWidth-5;
canvas.height = window.innerHeight-5;
}
</script>
</body>
</html>
\ No newline at end of file
#!/bin/bash
import os
basedir = os.path.dirname(__file__)
def run_cmd(cmd):
full_cmd = ''
if basedir!='':
full_cmd = 'cd '+basedir+'; '
full_cmd += 'cd ..; '+cmd
print(full_cmd)
os.system(full_cmd)
run_cmd('rm -rf build/')
run_cmd('rm -rf build2/')
run_cmd('rm -rf index.*')
run_cmd('make clean')
#!/bin/bash
import os
basedir = os.path.dirname(__file__)
os.system(f'cd {basedir}; cp Makefile_emscripten ../')
os.system(f'cd {basedir}; rm -f index.html')
os.system(f'cd {basedir}; cd ..; emmake make -f Makefile_emscripten clean')
os.system(f'cd {basedir}; cd ..; emmake make -f Makefile_emscripten -j$(nproc)')
print('\n=========================================================================')
print('If the compilation succeed, run the following command in the root directory to test the webpage:')
print(f'$ emrun index.html')
#!/bin/bash
import os
import multiprocessing
basedir = os.path.dirname(__file__)
full_path = os.path.dirname(os.path.abspath(__file__))
executable_name = full_path.split('/')[-2]
def run_cmd(cmd):
full_cmd = ''
if basedir!='':
full_cmd = 'cd '+basedir+'; '
full_cmd += 'cd ..; '+cmd
print(full_cmd)
os.system(full_cmd)
run_cmd('python3 scripts/linux_clean.py')
run_cmd('mkdir build/')
run_cmd('cd build/; cmake ..')
run_cmd('cd build/; make -j'+str(multiprocessing.cpu_count()))
run_cmd('cd build/; ./'+executable_name)
\ No newline at end of file
@ECHO OFF
Rem Make sure we are in the directory containing the .bat script
cd %~dp0
Rem Go to the root directory
cd ..
Rem Remove build/ if it exists
if exist build\ (
ECHO Remove build/
RMDIR /s /q "build"
)
for %%f in (*.pdb) do (
ECHO Remove %%f
DEL %%f
)
if exist imgui.ini (
ECHO Remove imgui.ini
DEL imgui.ini
)
ECHO.
ECHO Directory Cleaned
ECHO.
PAUSE
\ No newline at end of file
@ECHO OFF
Rem Make sure we are in the directory containing the .bat script
cd %~dp0
Rem Go to the root directory
cd ..
Rem Created build/ if needed
if not exist build\ (
ECHO Generate build/ directory
ECHO mkdir build
mkdir build
) else (
ECHO Found existing build/ directory
)
ECHO.
ECHO Run CMake (from build/ directory)
ECHO ===============================
cd build/
cmake .. && (
ECHO.
ECHO ===============================
ECHO CMAKE Generated with success
ECHO The project can be loaded from the .sln file in build/ directory
ECHO.
) || (
ECHO.
ECHO ===============================
ECHO CMAKE Failed to generate the project
ECHO Please check the error indicated by CMAKE
ECHO.
)
Rem The previous command call cmake with the default target project
Rem Specific targets use -G option from cmake
Rem ex. cmake -G "Visual Studio 17 2020" ..
PAUSE
\ No newline at end of file
@ECHO OFF
Rem Assume MinGW installed and configured via MSYS2 https://www.msys2.org/
Rem mingw32-make.exe must be in the windows path (you may follow this tutorial https://code.visualstudio.com/docs/languages/cpp for installation)
Rem Make sure we are in the directory containing the .bat script
cd %~dp0
Rem Go to the root directory
cd ..
Rem Created build/ if needed
if not exist build\ (
ECHO Generate build/ directory
ECHO mkdir build
mkdir build
) else (
ECHO Found existing build/ directory
)
ECHO.
ECHO Run CMake (from build/ directory)
ECHO ===============================
cd build/
cmake -G "MinGW Makefiles" .. && (
ECHO.
ECHO ===============================
ECHO CMAKE Generated with success
ECHO.
) || (
ECHO.
ECHO ===============================
ECHO CMAKE Failed to generate the project
ECHO Please check the error indicated by CMAKE
ECHO.
)
ECHO.
ECHO Start Compiling
ECHO.
mingw32-make.exe -j8
ECHO.
ECHO If the compilation suceed, the executable file should be in the build/ directory
ECHO.
PAUSE
\ No newline at end of file
@ECHO OFF
Rem Assume Visual Studio is installed
Rem Make sure we are in the directory containing the .bat script
cd %~dp0
Rem Go to the root directory
cd ..
ECHO Run CMake (from build/ directory)
ECHO ===============================
cmake -B build/ && (
ECHO.
ECHO ===============================
ECHO CMAKE Generated with success
ECHO.
) || (
ECHO.
ECHO ===============================
ECHO CMAKE Failed to generate the project
ECHO Please check the error indicated by CMAKE
ECHO.
)
ECHO.
ECHO Start Compiling
ECHO.
cmake --build build/ --config RelWithDebInfo
PAUSE
\ No newline at end of file
#version 330 core // Header for OpenGL 3.3
// Fragment shader - this code is executed for every pixel/fragment that belongs to a displayed shape
//
// Compute the color using Phong illumination (ambient, diffuse, specular)
// There is 3 possible input colors:
// - fragment_data.color: the per-vertex color defined in the mesh
// - material.color: the uniform color (constant for the whole shape)
// - image_texture: color coming from the texture image
// The color considered is the product of: fragment_data.color x material.color x image_texture
// The alpha (/transparent) channel is obtained as the product of: material.alpha x image_texture.a
//
// Inputs coming from the vertex shader
in struct fragment_data
{
vec3 position; // position in the world space
vec3 normal; // normal in the world space
vec3 color; // current color on the fragment
vec2 uv; // current uv-texture on the fragment
} fragment;
// Output of the fragment shader - output color
layout(location=0) out vec4 FragColor;
// Uniform values that must be send from the C++ code
// ***************************************************** //
uniform sampler2D image_texture; // Texture image identifiant
uniform mat4 view; // View matrix (rigid transform) of the camera - to compute the camera position
uniform vec3 light; // position of the light
// Coefficients of phong illumination model
struct phong_structure {
float ambient;
float diffuse;
float specular;
float specular_exponent;
};
// Settings for texture display
struct texture_settings_structure {
bool use_texture; // Switch the use of texture on/off
bool texture_inverse_v; // Reverse the texture in the v component (1-v)
bool two_sided; // Display a two-sided illuminated surface (doesn't work on Mac)
};
// Material of the mesh (using a Phong model)
struct material_structure
{
vec3 color; // Uniform color of the object
float alpha; // alpha coefficient
phong_structure phong; // Phong coefficients
texture_settings_structure texture_settings; // Additional settings for the texture
};
uniform material_structure material;
void main()
{
// Compute the position of the center of the camera
mat3 O = transpose(mat3(view)); // get the orientation matrix
vec3 last_col = vec3(view*vec4(0.0, 0.0, 0.0, 1.0)); // get the last column
vec3 camera_position = -O*last_col;
// Renormalize normal
vec3 N = normalize(fragment.normal);
// Inverse the normal if it is viewed from its back (two-sided surface)
// (note: gl_FrontFacing doesn't work on Mac)
if (material.texture_settings.two_sided && gl_FrontFacing == false) {
N = -N;
}
// Phong coefficient (diffuse, specular)
// *************************************** //
// Unit direction toward the light
vec3 L = normalize(light-fragment.position);
// Diffuse coefficient
float diffuse_component = max(dot(N,L),0.0);
// Specular coefficient
float specular_component = 0.0;
if(diffuse_component>0.0){
vec3 R = reflect(-L,N); // symetric of light-direction with respect to the normal
vec3 V = normalize(camera_position-fragment.position);
specular_component = pow( max(dot(R,V),0.0), material.phong.specular_exponent );
}
// Texture
// *************************************** //
// Current uv coordinates
vec2 uv_image = vec2(fragment.uv.x, fragment.uv.y);
if(material.texture_settings.texture_inverse_v) {
uv_image.y = 1.0-uv_image.y;
}
// Get the current texture color
vec4 color_image_texture = texture(image_texture, uv_image);
if(material.texture_settings.use_texture == false) {
color_image_texture=vec4(1.0,1.0,1.0,1.0);
}
// Compute Shading
// *************************************** //
// Compute the base color of the object based on: vertex color, uniform color, and texture
vec3 color_object = fragment.color * material.color * color_image_texture.rgb;
// Compute the final shaded color using Phong model
float Ka = material.phong.ambient;
float Kd = material.phong.diffuse;
float Ks = material.phong.specular;
vec3 color_shading = (Ka + Kd * diffuse_component) * color_object + Ks * specular_component * vec3(1.0, 1.0, 1.0);
// Output color, with the alpha component
FragColor = vec4(color_shading, material.alpha * color_image_texture.a);
}
\ No newline at end of file
#version 330 core // Header for OpenGL 3.3
// Vertex shader - this code is executed for every vertex of the shape
// Inputs coming from VBOs
layout (location = 0) in vec3 vertex_position; // vertex position in local space (x,y,z)
layout (location = 1) in vec3 vertex_normal; // vertex normal in local space (nx,ny,nz)
layout (location = 2) in vec3 vertex_color; // vertex color (r,g,b)
layout (location = 3) in vec2 vertex_uv; // vertex uv-texture (u,v)
// Output variables sent to the fragment shader
out struct fragment_data
{
vec3 position; // vertex position in world space
vec3 normal; // normal position in world space
vec3 color; // vertex color
vec2 uv; // vertex uv
} fragment;
// Uniform variables expected to receive from the C++ program
uniform mat4 model; // Model affine transform matrix associated to the current shape
uniform mat4 view; // View matrix (rigid transform) of the camera
uniform mat4 projection; // Projection (perspective or orthogonal) matrix of the camera
uniform mat4 modelNormal; // Model without scaling used for the normal. modelNormal = transpose(inverse(model))
void main()
{
// The position of the vertex in the world space
vec4 position = model * vec4(vertex_position, 1.0);
// The normal of the vertex in the world space
vec4 normal = modelNormal * vec4(vertex_normal, 0.0);
// The projected position of the vertex in the normalized device coordinates:
vec4 position_projected = projection * view * position;
// Fill the parameters sent to the fragment shader
fragment.position = position.xyz;
fragment.normal = normal.xyz;
fragment.color = vertex_color;
fragment.uv = vertex_uv;
// gl_Position is a built-in variable which is the expected output of the vertex shader
gl_Position = position_projected; // gl_Position is the projected vertex position (in normalized device coordinates)
}
#version 300 es // Compatible with OpenGL ES
precision mediump float;
// Fragment shader - this code is executed for every pixel/fragment that belongs to a displayed shape
//
// Compute the color using Phong illumination (ambient, diffuse, specular)
// There is 3 possible input colors:
// - fragment_data.color: the per-vertex color defined in the mesh
// - material.color: the uniform color (constant for the whole shape)
// - image_texture: color coming from the texture image
// The color considered is the product of: fragment_data.color x material.color x image_texture
// The alpha (/transparent) channel is obtained as the product of: material.alpha x image_texture.a
//
// Inputs coming from the vertex shader
in struct fragment_data
{
vec3 position; // position in the world space
vec3 normal; // normal in the world space
vec3 color; // current color on the fragment
vec2 uv; // current uv-texture on the fragment
} fragment;
// Output of the fragment shader - output color
layout(location=0) out vec4 FragColor;
// Uniform values that must be send from the C++ code
// ***************************************************** //
uniform sampler2D image_texture; // Texture image identifiant
uniform mat4 view; // View matrix (rigid transform) of the camera - to compute the camera position
uniform vec3 light; // position of the light
// Coefficients of phong illumination model
struct phong_structure {
float ambient;
float diffuse;
float specular;
float specular_exponent;
};
// Settings for texture display
struct texture_settings_structure {
bool use_texture; // Switch the use of texture on/off
bool texture_inverse_v; // Reverse the texture in the v component (1-v)
bool two_sided; // Display a two-sided illuminated surface (doesn't work on Mac)
};
// Material of the mesh (using a Phong model)
struct material_structure
{
vec3 color; // Uniform color of the object
float alpha; // alpha coefficient
phong_structure phong; // Phong coefficients
texture_settings_structure texture_settings; // Additional settings for the texture
};
uniform material_structure material;
void main()
{
// Compute the position of the center of the camera
mat3 O = transpose(mat3(view)); // get the orientation matrix
vec3 last_col = vec3(view*vec4(0.0, 0.0, 0.0, 1.0)); // get the last column
vec3 camera_position = -O*last_col;
// Renormalize normal
vec3 N = normalize(fragment.normal);
// Inverse the normal if it is viewed from its back (two-sided surface)
// (note: gl_FrontFacing doesn't work on Mac)
if (material.texture_settings.two_sided && gl_FrontFacing == false) {
N = -N;
}
// Phong coefficient (diffuse, specular)
// *************************************** //
// Unit direction toward the light
vec3 L = normalize(light-fragment.position);
// Diffuse coefficient
float diffuse_component = max(dot(N,L),0.0);
// Specular coefficient
float specular_component = 0.0;
if(diffuse_component>0.0){
vec3 R = reflect(-L,N); // symetric of light-direction with respect to the normal
vec3 V = normalize(camera_position-fragment.position);
specular_component = pow( max(dot(R,V),0.0), material.phong.specular_exponent );
}
// Texture
// *************************************** //
// Current uv coordinates
vec2 uv_image = vec2(fragment.uv.x, fragment.uv.y);
if(material.texture_settings.texture_inverse_v) {
uv_image.y = 1.0-uv_image.y;
}
// Get the current texture color
vec4 color_image_texture = texture(image_texture, uv_image);
if(material.texture_settings.use_texture == false) {
color_image_texture=vec4(1.0,1.0,1.0,1.0);
}
// Compute Shading
// *************************************** //
// Compute the base color of the object based on: vertex color, uniform color, and texture
vec3 color_object = fragment.color * material.color * color_image_texture.rgb;
// Compute the final shaded color using Phong model
float Ka = material.phong.ambient;
float Kd = material.phong.diffuse;
float Ks = material.phong.specular;
vec3 color_shading = (Ka + Kd * diffuse_component) * color_object + Ks * specular_component * vec3(1.0, 1.0, 1.0);
// Output color, with the alpha component
FragColor = vec4(color_shading, material.alpha * color_image_texture.a);
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment