I'm not sure I understand which part you have working and which you don't.
Did you say that you're drawing the shape on the render texture?
The render texture should be filled with the texture; it can be a rectangle. The shape/vertex array is drawn to the window using the render texture as its texture. This is the vertex array that should use texture co-ordinates similar to positions.
This way, it's like the shape you draw become a "cookie-cutter" for the texture passed to it (your render texture's texture).
I'm not sure why you're using a sprite...
I've written a more thorough example that shows a render texture getting used as a texture for slightly more complicated shapes.
Similarly to the previous example, it creates the circle points but this time it randomly scales their radii, creating a 'random spikey' object.
I've also added comments to explain a little better what is going on.
I hope it's easy enough for you to follow as it's still C++.
Here are 3 screenshots from this program:
Here's the code with comments:
// this generates a randomised triangle fan using a render texture as its texture base
// it shows that the (render) texture need not know the final shape on which it is used
// the shape can be re-generated by pressing SPACE
#include <SFML/Graphics.hpp>
#include <random>
#include <functional>
#include <iostream>
bool generateRenderTexture(sf::RenderTexture& renderTexture)
{
// Load texture
sf::Texture texture;
if (!texture.loadFromFile("uv map 1.jpg")) // the image I used here is sized 256x256
return false;
renderTexture.create(texture.getSize().x, texture.getSize().y);
renderTexture.clear();
renderTexture.draw(sf::Sprite(texture)); // draw the full texture onto the render texture
renderTexture.display();
// at this point, we have a render texture that is exactly the same size as the texture and is visually indentical to the texture; we can now use it as a normal texture
// if you want to use a gradient, say, instead of an image then create a square that fills the render texture with the gradient and draw it to the render texture instead
return true;
}
void prepareVertices(sf::VertexArray& shape, const sf::Vector2u size)
{
// prepare random
std::default_random_engine randomGenerator;
randomGenerator.seed(std::random_device()());
std::uniform_real_distribution<float> randomAlphaDistribution{ 0.f, 1.f }; // "alpha" distribution (from 0 to 1)
// properties
const sf::Vector2f shapeOffset{ 128.f, 64.f };
const std::size_t numberOfSides{ shape.getVertexCount() - 2u };
// this calculates the points of a circle from vertex 1 onwards; vertex 0 is the centre of the circle (the start of the triangle fan)
// each of those points have their radii scaled randomly to create a random 'pointy' shape
// these points are convertex from their original range (-1 to 1) to a normalised range (0 to 1)
// this means that the origin (0, 0) is a the top-left of the circle's bounding box
// it is then scaled to match the size of the render texture
// the vertex positions are then offset by "shapeOffset" to allow the shape to move away from the origin without moving which part of the texture is used
for (std::size_t i{ 0u }; i < shape.getVertexCount(); ++i)
{
sf::Vector2f position; // normalised circular vertices ranging from 0 - 1 with centre at (0.5, 0.5)
sf::Vector2f texturePosition; // (position scaled to size)
if (i == 0)
position = { 0.5f, 0.5f }; // first vertex is in the centre to begin the triangle fan
else
{
// calculate circle point's position using sine and cosine. the radius of this point is scaled by a random value
const float angle{ static_cast<float>(i - 1u) / numberOfSides * 2.f * 3.14159265358979f };
const sf::Vector2f circlePoint{ std::cos(angle), std::sin(angle) }; // ranging from -1 to 1 on each axis
const float radiusScale{ randomAlphaDistribution(randomGenerator) }; // scale the radius of each point separately by a random amount
position = { (1.f + std::cos(angle) * radiusScale) / 2.f, (1.f + std::sin(angle) * radiusScale) / 2.f }; // ranging from 0 to 1 on each axis
}
texturePosition = { position.x * size.x, position.y * size.y };
shape[i].position = texturePosition + shapeOffset;
shape[i].texCoords = texturePosition;
}
}
int main()
{
// prepare random
std::default_random_engine randomGenerator;
randomGenerator.seed(std::random_device()());
std::uniform_real_distribution<float> randomAlphaDistribution{ 0.f, 1.f }; // "alpha" distribution (from 0 to 1)
// Prepare render texture
sf::RenderTexture renderTexture;
if (!generateRenderTexture(renderTexture))
return EXIT_FAILURE;
// Prepare shape
constexpr std::size_t numberOfSides{ 36u };
sf::VertexArray shape;
shape.resize(numberOfSides + 2u);
shape.setPrimitiveType(sf::TrianglesFan);
// Generate vertices for shape (circle but with each point having a random radius)
prepareVertices(shape, renderTexture.getSize());
// Create window and display shape
sf::RenderWindow window(sf::VideoMode(512, 384), "Tex Coords", sf::Style::Default);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
switch (event.type)
{
case sf::Event::Closed:
window.close();
break;
case sf::Event::KeyPressed:
switch (event.key.code)
{
case sf::Keyboard::Escape:
window.close();
break;
case sf::Keyboard::Space:
prepareVertices(shape, renderTexture.getSize()); // re-generate vertices (randomised)
break;
}
break;
}
}
window.clear(sf::Color(128, 128, 128));
window.draw(shape, &renderTexture.getTexture()); // draw the vertex array using our render texture
window.display();
}
return EXIT_SUCCESS;
}
EDIT: added new example