Created
June 5, 2015 22:59
-
-
Save paulhoux/f98391b526efa6b928d9 to your computer and use it in GitHub Desktop.
Example of how to create a texture from code. Here, we create a gradient texture.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cinder/app/App.h" | |
#include "cinder/app/RendererGl.h" | |
#include "cinder/gl/gl.h" | |
using namespace ci; | |
using namespace ci::app; | |
using namespace std; | |
typedef std::pair<float, ColorA> ColorStop; | |
class GradientApp : public App { | |
public: | |
void setup() override; | |
void draw() override; | |
//! Creates a gradient texture from a list of colors and stops. | |
gl::Texture2dRef createGradient( const std::vector<ColorStop> &colors, uint16_t width = 256, uint16_t height = 1 ); | |
private: | |
gl::Texture2dRef mGradient; | |
}; | |
void GradientApp::setup() | |
{ | |
// Example gradient. | |
std::vector<ColorStop> gradient; | |
gradient.push_back( std::make_pair( 0.0f, Color( 1, 0, 0 ) ) ); | |
gradient.push_back( std::make_pair( 0.16f, Color( 1, 1, 0 ) ) ); | |
gradient.push_back( std::make_pair( 0.33f, Color( 0, 1, 0 ) ) ); | |
gradient.push_back( std::make_pair( 0.50f, Color( 0, 1, 1 ) ) ); | |
gradient.push_back( std::make_pair( 0.66f, Color( 0, 0, 1 ) ) ); | |
gradient.push_back( std::make_pair( 0.83f, Color( 1, 0, 1 ) ) ); | |
gradient.push_back( std::make_pair( 1.0f, Color( 1, 0, 0 ) ) ); | |
// Create the texture. | |
mGradient = createGradient( gradient, 512, 32 ); | |
} | |
void GradientApp::draw() | |
{ | |
gl::clear(); | |
gl::draw( mGradient ); | |
} | |
// For simplicity, assume that the colors are specified in the right order and range (from 0 to 1). | |
gl::Texture2dRef GradientApp::createGradient( const std::vector<ColorStop>& colors, uint16_t width, uint16_t height ) | |
{ | |
// Create a data buffer with enough space for all pixels of 4 bytes each. | |
std::vector<uint8_t> buffer; | |
buffer.resize( width * height * 4 ); | |
// Now read the gradient info and fill the buffer with BGRA colors. | |
for( size_t i = 0; i < colors.size() - 1; ++i ) { | |
auto &color1 = colors[i]; | |
auto &color2 = colors[i + 1]; | |
// Sanity check. | |
CI_ASSERT( color1.first >= 0 && color1.first <= 1 ); | |
CI_ASSERT( color2.first >= 0 && color2.first <= 1 ); | |
CI_ASSERT( color1.first < color2.first ); | |
// Convert float to a value between 0 and 255. | |
uint16_t stop1 = uint16_t( color1.first * ( width - 1 ) ); | |
uint16_t stop2 = uint16_t( color2.first * ( width - 1 ) ); | |
for( uint16_t x = stop1; x <= stop2; ++x ) { | |
// Calculate color. | |
float f = ( x - stop1 ) / float( stop2 - stop1 ); | |
ColorA c = lerp( color1.second, color2.second, f ); | |
// Convert to BGRA bytes and store in buffer. | |
for( uint16_t y = 0; y < height; ++y ) { | |
buffer[( width * y + x ) * 4 + 0] = uint8_t( c.b * 255 ); | |
buffer[( width * y + x ) * 4 + 1] = uint8_t( c.g * 255 ); | |
buffer[( width * y + x ) * 4 + 2] = uint8_t( c.r * 255 ); | |
buffer[( width * y + x ) * 4 + 3] = uint8_t( c.a * 255 ); | |
} | |
} | |
} | |
// Create a texture from the data. | |
Surface8u texture = Surface8u( buffer.data(), width, height, width * 4, SurfaceChannelOrder::BGRA ); | |
return gl::Texture2d::create( texture ); | |
} | |
CINDER_APP( GradientApp, RendererGl ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment