Skip to content

Instantly share code, notes, and snippets.

@paulhoux
Created June 5, 2015 22:59
Show Gist options
  • Save paulhoux/f98391b526efa6b928d9 to your computer and use it in GitHub Desktop.
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.
#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